Search code examples
javapolymorphismoverridingcovariance

Java method overriding covariance inquiry


I have an inquiry about method overriding covariance .. Let's say we have two classes as follows:

class Parent {
   Object getSomething(){
      return 10;
   }
}

class Child extends Parent {
   Integer getSomething() {
      return 10;
   }
}

class TestCovariance {
   public static void main(String[] args) {
      Child c = new Child();
      Parent p = new Child();

      Integer i1 = c.getSomething(); //this is ok
      Integer i2 = p.getSomething(); //this one gives a runtime exception
   }
}

As you see in the comment of that line that gives a runtime exception, exception details:

Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - incompatible types: java.lang.Object cannot be converted to java.lang.Integer

Why does it see the method of c object returns an Integer while the method of p object returns an Object??


Solution

  • First, I'd like to re-iterate that covariant return types is the ability to change the return type of the overriding method to a subtype of the overridden methods return type which in your case seems correct.

    The call to Integer i1 = c.getSomething(); compiles successfully because the receiver type is of Child and the compiler knows that the return type of c.getSomething() is Integer.

    However on the other hand, due to the fact that you're using Parent as the receiver type of p, only the methods of the Parent class are visible through this reference even if the actual object p is referring to is a Child and obviously p.getSomething() is assumed to return Object at compile time and you're attempting to assign it to an Integer, hence the compilation error.

    Having said that the call Integer i2 = p.getSomething(); could succeed at runtime but as mentioned it's a compile-time error as the compiler checks and ensures that you only invoke methods that exist for the receiver type.

    Also as mentioned by davidxxx:

    the RuntimeException is thrown but it is not thrown by the program itself but the IDE as it "discovers" that the started program has a uncompilable class.