My problem with the following example is that I have read that if you override a function, the return type cannot be changed unless you are overriding in a descendant object, in which case you may change the return type from ParentClass
to ChildClass
but that is not the case in either of these cases. We change the return type from String to Object in the first example, and from Object to String in the second one, neither of which are class A or B. Maybe it is the case that you can return a more specific type in any overridden functions?
I: This one is definitely false because you are returning a more general type when overriding.
public class Test {
public static void main(String[] args) {
A a = new A();
System.out.println(a.getValue());
}
}
class B {
public String getValue() {
return "Any object";
}
}
class A extends B {
public Object getValue() {
return "A string";
}
}
II: This must be the correct one but I don't understand because I thought you could only override from returning type B in class B to type A in class A. That that was the only exception and in previous versions of Java, even that wasn't allowed so I don't see how we can change Object to String.
public class Test {
public static void main(String[] args) {
A a = new A();
System.out.println(a.getValue());
}
}
class B {
public Object getValue() {
return "Any object";
}
}
class A extends B {
public String getValue() {
return "A string";
}
}
The second is fine, because of this rule in JLS 8.4.8.3:
If a method declaration d1 with return type R1 overrides or hides the declaration of another method d2 with return type R2, then d1 must be return-type-substitutable (ยง8.4.5) for d2, or a compile-time error occurs.
This rule allows for covariant return types - refining the return type of a method when overriding it.
Object
is the superclass of String
, so it's fine for a method previously declared to return Object
is refined in a subclass override to return String
.
It's fine because any code which only knows about the superclass method is going to use the return value as Object
, and it's fine to use any String
reference as an Object
reference, e.g.
String x = ...; // Anything here
Object y = x; // No problem
It sounds like you're getting confused between the two pairs of types here::
Those are four completely separate classes - here B
, A
, Object
and String
respectively.
See more on this question at Stackoverflow