When a subclass object is casted to its superclass, for example
Superclass obj = new Subclass();
and the classes were defined
public class Superclass{
public void thisMethod(){
System.out.println("Superclass version was executed");
}
and
public class Subclass extends Superclass{
public void thisMethod(){
System.out.println("Subclass version was called");
}
public void newMethod(){
System.out.println("blah");
}
}
When obj.thisMethod()
was called, I get Subclass version was called
as the output, which obviously means the version of this method which was defined in the subclass(the version which an original Superclass object cannot "perform") was called, although the declared type is Superclass, yes?
So, if even though the subclass method was executed on obj,
when obj.newMethod()
is called, I get a compile error.
Basically, why is the version of thisMethod()
defined in the subclass being invoked through the Superclass object obj
? I understand that the actual type of obj
is still Subclass, so naturally, the new version should get called, but then, shouldn't I be able to call obj.newMethod()
?
Thanks heaps for any explanations (:
edit: meant overridden* in the title
Basically, why is the version of thisMethod() defined in the subclass being invoked through the Superclass object obj?
Because that's basically the point of inheritance - it allows an implementation to override, without the calling code needing to know which implementation is being used. Take InputStream
as an example - you can code using InputStream
, and then the same code will work whether you're passed a FileInputStream
, a ByteArrayInputStream
etc. In the case of an abstract class or interface, you may be calling methods which don't have any implementation in the compile-time type - but it's guaranteed that there'll be an implementation in the concrete object type being used at execution time.
I understand that the actual type of obj is still Subclass, so naturally, the new version should get called, but then, shouldn't I be able to call
obj.newMethod()
?
No, because the compile-time type of obj
is Superclass
. It's really important to differentiate between the compile-time type of a variable, which determines which methods etc are available, and the execution-time type of the object that the variable's value refers to, which determines which method implementations are actually called.
That's just a very brief description - you should read a good Java book's chapter on inheritance for more details.
See more on this question at Stackoverflow