2009-04-23 44 views
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; }引发编译错误。这是为什么?有人可以解释为什么“对象”类型是不可能的吗? Object是Class One,Two的基类吗?如果那么为什么它会抛出一个错误?Java类问题

请改变问题的标题,因为我找不到合适的标题。

回答

16

Three.foo正在尝试覆盖Two.foo(),但它没有正确执行。假设我写:

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

忽略的事实,实际上Three.foo()确实返回OneThree.foo()签名并不能保证它。因此,不得不返回One

请注意,您可以改变返回类型,仍然覆盖,但它必须是具体的,而不是。换句话说,这会好起来的:

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

因为ThreeOne更具体。

5

您正在以不支持的方式更改foo方法的签名。多态性仅适用于不同的参数列表,而不适用于仅返回类型不同的相同方法。

如果你考虑一下,这是很自然的......如果它工作,并且只知道两个超类之一的人会打电话给Three.foo(),他会希望它返回一个(因为这就是它在One和Two中的工作原理),但在Three中,你实际上可以返回一个HashMap并且仍然正确。

Jon(在下面的评论中)是正确的,你可以缩小范围,但是你仍然会遵循协议,你将返回一个“One”(你应该从Three.foo()返回Three),因为子类将全部实现超类接口。 但是,返回类型仍然不是多态的一部分,因此您不能有三种不同的方法,这些方法只会因返回类型而有所不同。

+1

不正确。您可以通过使返回类型*更具体*来覆盖。 – 2009-04-23 09:32:08

2

它将使:

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

重写的方法,并试图返回一个不太具体类型是Liskov substitution principle的侵犯,它说,子类必须履行其超类的所有合同。你的类三违反超类契约“foo()返回一个”的实例“。