Determining which overrides method is actually invoked

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

Jon Skeet
people
quotationmark

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.

people

See more on this question at Stackoverflow