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; }
抛出编译错误。这是为什么?有人可以解释为什么“对象”类型不可能吗?对象是Class One,Two的基类吗?如果那么为什么会抛出错误?
请更改问题的标题,因为我无法找到合适的标题。
答案 0 :(得分:16)
Three.foo
正在尝试覆盖Two.foo()
,但它没有正确执行。假设我要写:
One f = new Three();
One other = f.foo();
忽略实际 Three.foo()
的事实返回One
,Three.foo()
的签名并不能保证。因此,对于 必须返回One
的方法,它不是一个合适的覆盖。
请注意,您可以更改返回类型并仍然覆盖,但必须更多特定而不是 less 。换句话说,这没关系:
class Three extends Two {
public Three foo() { return this; }
}
因为Three
比One
更具体。
答案 1 :(得分:5)
您正在以不支持的方式更改foo方法的签名。多态性仅适用于不同的参数列表,不适用于仅由返回类型不同的相同方法。
如果你考虑一下,这很自然......如果它有效并且只知道两个超类之一的人会调用Three.foo()他会期望它返回一个(因为那个)它是如何在One和Two中工作的)但在Three中你实际上可以返回一个HashMap并且仍能正常运行。
Jon(在下面的评论中)是正确的,你可以缩小范围但是你仍然会遵循你将返回“One”的协议(你应该从Three.foo()返回一个三)因为子类将都实现了超类接口。 但是,返回类型仍然不是多态的一部分,因此您不能有三种不同的方法,只有不同的返回类型。
答案 2 :(得分:2)
它将启用:
class Four extends Three {
public Object foo() { return "This String is not an instance of One"; }
}
答案 3 :(得分:2)
覆盖方法并尝试返回不太具体的类型违反了Liskov substitution principle,它表示子类必须满足其超类的所有合同。你的第三类违反了超类合同“foo()返回一个实例”。