Why do we need Downcasting really?

b4da picture b4da · Jul 16, 2013 · Viewed 9.5k times · Source

I am trying to figure out why do I need Downcasting. I reread my notes from collage and found the below example.

class Student {...}

class Graduate exteds Student {
   getResearchTopic(){...} // this method only exists in Graduate class.
}

We have a ref to Student class and want to access to getResearchTopic method;

Student s1 = new Graduate();
if(s1 instanceof Graduate){
   ((Graduate)s1).getResearchTopic();
}

Great example for Downcasting hah? My question is Why not declare s1 as a Graduate in the first place? Is there a real life example where I will have to downcast instead of using an instance of actual class?

Answer

Rohit Jain picture Rohit Jain · Jul 16, 2013

Well, you could have declared the reference s1 to be of type Graduate. The main benefit you get by declaring the reference of super type, is the power of polymorphism.

With a super type reference, pointing to a sub class object, you can bind the same reference to multiple sub class objects. And the actual method invoked will be decided at runtime, based on what object is being pointed to. But, the main condition for this is, that method should also be defined in the subclass, else the compiler will fail to find the method declaration.

Here, you were forced to downcast, because you haven't defined the method in the super class. As compiler cannot see the definition of that method in Student class. It has no idea about what the actual object s1 points to. Remember, compiler only checks the reference type to find the meethod declaration.

In general, whenever you see yourself downcasting to a subclass in your code, it is almost always a sign a something wrong (there are some exceptions though). And you should modify your classes.


Let's see what benefit you get by using a super class reference instead of a subclass reference:

For e.g: Suppose you have another sub class of Student as:

class Phd extends Student {
    getResearchTopic(){...}
}

and you also provide a definition (a default one) in Student class:

class Student {
    getResearchTopic(){...}
}

Now, you create a following two objects, both being pointed to by Student reference:

Student student = new Phd();
student.getResearchTopic();   // Calls Phd class method

student = new Graduate();
student.getResearchTopic();    // Calls Graduate class method

So, with only a single reference, you get to access methods specific to subclasses.


One major implementation of this feature you can see in factory method pattern, where a single static method returns an object of different sub classes based on some condition:

public static Student getInstance(String type) {
    if (type.equals("graduate")) 
        return new Graduate();
    else if (type.equals("phd"))
        return new Phd();
}

So, you can see that the same method returns an object of different subclasses.

All of the above stuffs you can do just because of one concept:

A Super class reference can refer to any sub class objects, but not vice-versa.