4
class One {
public One foo() { return this; }
}

class Two extends One {
public One foo() { return this; }
}

class Three extends Two {
public Object foo() { return this; }
}

public Object foo() { return this; } throws a compilation error. Why is that? Can someone explain why "Object" type is not possible? Is Object the base class of Class One, Two? If So why does it throws an error?

Please change the title of the question as I couldnt find a suitable title.

4 Answers 4

16

Three.foo is trying to override Two.foo(), but it doesn't do it properly. Suppose I were to write:

One f = new Three();
One other = f.foo();

Ignoring the fact that actually Three.foo() does return a One, the signature of Three.foo() doesn't guarantee it. Therefore it's not an appropriate override for a method which does have to return a One.

Note that you can change the return type and still override, but it has to be more specific rather than less. In other words, this would be okay:

class Three extends Two {
    public Three foo() { return this; }
}

because Three is more specific than One.

Sign up to request clarification or add additional context in comments.

Comments

5

You are changing the signature of the foo method in a way not supported. Polymorphism only works for different argument list, not for identical methods only different by the return type.

And if you think about it, it is quite natural... If it worked and someone who only knows about one of the two super classes would call Three.foo() he would expect it to return a One (because that is how it works in One and Two) but in Three you could actually return a HashMap and still behave correctly.

Jon (in the comment below) is correct, you can narrow the scope but then you would still follow the protocol that you will return a "One" (should you return a Three from Three.foo()) because subclasses will all implement the superclass interface. However, return type is still not part of the polymorphism, hence you cannot have three different methods that only differs by return type.

2 Comments

Not true. You can override by making the return type more specific.
I was about to say that in an edit but you were two quick for me :-)
2

It would enable:

class Four extends Three {
public Object foo() { return "This String is not an instance of One"; }
}

Comments

2

Overriding a method and trying to return a less specific type is a violation of the Liskov substitution principle, which says that subclasses must fulfill all contracts of their superclass. Your class Three violates the superclass contract "foo() returns an instance of One".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.