Upcasting a subclass reference in Java

899 views Asked by At

I'm doing the following exercise in Thinking in Java 4th Edition by Bruce Eckel:

Exercise 16: (2) Create a class called Amphibian. From this, inherit a class called Frog. Put appropriate methods in the base class. In main(), create a Frog and upcast it to Amphibian and demonstrate that all the methods still work.

What is the difference between Frog f = new Frog(); and Amphibian f = new Frog(); in:

class Amphibian {
    void go() { System.out.println("go"); }
    void stop() { System.out.println("stop!"); }
}

class Frog extends Amphibian {
    void go() { System.out.println("not go"); }
}

public class EFrog {
    public static void main(String[] args) {
        Frog f = new Frog();
        f.go();
    }
}
6

There are 6 answers

0
Chetan Kinger On BEST ANSWER

But I don't understand What is the difference between Frog f = new Frog(); and Amphibian f = new Frog();

To understand the difference, let's add another method in Frog that is not in Amphibian

class Frog extends Amphibian {
    void go() { System.out.println("not go"); }
    void come() { System.out.println("come"); }
}

Now let's take a look at what's the difference :

public class EFrog {
    public static void main(String[] args) {
        Frog f = new Frog();
        f.go();
        f.come();
        Amphibian a = f;
        a.come();//this won't compile
    }
}

Bottom line. Frog is an Amphibian so Frog can do whatever an Amphibian can. Amphibian is not a Frog so Amphibian can't do everything a Frog can.

When you say Amphibian a = new Frog(), you are programming to an interface (not the java interface but the general meaning of interface). When you say Frog f = new Frog() you are programming to an implementation.

Now coming to the actual question that the book asks you to try :

In main( ), create a Frog and upcast it to Amphibian and demonstrate that all the methods still work.

public class EFrog {
        public static void main(String[] args) {
            Frog f = new Frog();
            Amphibian g = (Amphibian)f;//this is an upcast
            g.go(); //okay since Amphibian can go
            g.come();//not okay since Amphibian can't come                
        }
    }

I don't think you meant to ask What's the use of upcasting but since the title has already been edited by someone else, why not answer that as well? Upcasting is useful in certain situations such as calling specialized forms of an overloaded methods explicitly. See this answer for additional details.

0
Blip On

What is the difference between Frog f = new Frog(); and Amphibian f = new Frog();

From your example we can see that Frog inherits Amphibian. So any variable that is declared of type Amphibian can always store instance of objects which have super class as Amphibian in your case Frog. As for the example code it has no difference.

But there is a subtle difference between the two that can not be found in your example. Consider the following:

class Frog extends Amphibian {
    void go() { System.out.println("not go"); }
    void croak(){ System.out.println("croak");} //Added this extra line
}

Now if you store your Frog instance as

Amphibian f = new Frog();
f.croak(); //This will not work.

This is not working as because the JVM considers f as type Amphibian and in Amphibian class there is no method croak. So an error is thrown. But if you store it like:

Frog f = new Frog();
f.croak(); //This will work.

This is working because the JVM considers f as type Frog and the class Frog has the method croak.

Of course you can make the previous case work by type casting the f to Frog as :

Amphibian f = new Frog();
((Frog)f).croak(); //This will work.
0
user140547 On

In this simple program, there is actually no difference. But if you have a Amphibian f, it can refer to any amphibian, not just a Frog. You still use all methods that an Amphibian provides, even if it is an instance of a Frog See What is polymorphism, what is it for, and how is it used? for a description of polymorphism.

0
RehanZahoor On

This is what we know as polymorphism. That is many shapes. Many shapes of the same object. The same object can be referred to as Frog and it can be referred to as Amphibian, as you have learned. When referral is as Amphibian, still the original object is Frog so the overridden method is called.

0
dosw On

Too see the difference, you could add a method jump() to Frog (but not the to the base class Amphibian:

class Amphibian {
    void go() { System.out.println("go"); }
    void stop() { System.out.println("stop!"); }
}

class Frog extends Amphibian {
    void go() { System.out.println("not go"); }
    void jump() { System.out.println("jump!"); }
}

public class EFrog {
    public static void main(String[] args) {
        Frog f = new Frog();
        f.go();
        f.jump(); // works
        Amphibian a = new Frog();
        a.jump(); // will not compile!
    }
}
0
R9J On

This one is Simple If you use like below

Frog f = new Frog();

Then you can't cast it to any other type. However you can call all the Frog methods.

But If you use like below

Amphibian f = new Frog();

you can still change the object to some other amphibians without changing its reference by simply doing like this.

f = new SomeOtherAmphibian();

This way of coding is very popular and known as coding to the Base Class or Interface