Search code examples
javainheritancecastingdynamic-binding

Trying to understand casting and dynamic binding in terms of inheritance


Let's say I have a GrandParentClass that gets inherited by ParentClass which gets inherited by ChildClass.

Why can I only cast "up the chain" but not down?

Why can I only dynamic bind "down the chain" but not up?

I'm looking for some reasoning I can apply to these questions instead of just memorizing the pattern. I'm really hoping this isn't just a "that's just the way it is" kind of answer.

Example of casting:

ParentClass object = new ParentClass();
System.out.println((GrandParentClass)object);  //casting ChildClass throws compiler error 

Example of dynamic binding:

GrandParentClass = new ChildClass(); //Switching GrandParentClass with ChildClass throws run time error.

Solution

  • The general reasoning for these casting rules (not only in Java) is that inheritance allows you build trees of classes, not just lists. To put it differently, not every object of type GrandParentClass is necessarily an object of type ParentClass and not every object of type ParentClass is necessarily of type ChildClass. You could conceive an alternative ParentClass2 inheriting from GrandParentClass or simply instantiate an object of type GrandParentClass. Imagine what would happen if you were allowed to access a GrandParentClass object as if it was a ChildClass object with all the methods and variables that are defined only in ChildClass but not above. There is no meaningful resolution.

    So, casting "up the chain" always makes sense, since the inheritance relation is known at compile-time. Your dynamic binding example is the same thing; You are binding "up the chain" (not at all "down the chain") since you are assigning a derived type object to a reference of a type it was derived from.