为什么在重写方法中不能放松参数类型?

时间:2012-04-09 00:58:20

标签: java override design-rationale

此代码无效:

interface Foo
{
    public void foo(final String string);
}

public class Bar implements Foo
{
    // Error: does not override.
    @Override public void foo(final Object object)
    {
    }
}

因为每个String显然都是Object,所以我希望这段代码非常合适:任何依赖于赋予foo() String的代码都会在foo()实际上需要Object

但是,似乎方法签名必须与它们覆盖的方法相同。为什么呢?

4 个答案:

答案 0 :(得分:4)

如果

怎么办?
interface Foo
{
    void foo(String string);
    void foo(Object string);
}

然后Bar会覆盖哪个方法?

答案 1 :(得分:0)

'松散',因为你说它不应该影响那些期望以特定方式使用你的接口定义方法的人,因为你在该对象上调用的任何方法理论上应该可以在指定对象上调用,但Eugene的观点是,因为如果你只是模糊地想要遵守接口规范,那么在确定你实际想要覆盖的方法时,可能会遇到一些令人头疼的问题。另外,如果你要坚持继续继承heirarchy,为什么这是可取的,因为你可以做到你想要的所有你想要的东西,例如'对象'的层次结构?可能在你的方法内部投射会解决你的问题?如果可以做你想做的事情,你也可能会开始研究多态性范例。

答案 2 :(得分:0)

我认为这是一个经典的逆变问题。你的接口需要一个字符串作为参数传递,你想要一个接受一个对象的实现(因为,毕竟,字符串也是对象)。

问题在于,如果您允许,那么您无法保证接口所需的参数是字符串或其任何一个祖先。您也可以将任何对象传递给您的实现,并且您将违反界面的合同,从而危及设计的类型安全性和类型连贯性。

你确实有选择:

public class Bar implements Foo
{

    @Override public void foo(final String object)
    {
    }

    public void foo(final Object object)
    {
       foo((String) object);
    }
}

通过这种方式,您将确保该对象实际上是一个字符串,使类型系统能够检查您是否确实遵守了方法签名中建立的接口契约。

是否存在特定情况,您认为您的逆向范例是必需的?

答案 3 :(得分:0)

它只是Java编程语言的构造。 Java程序的结构将在你身上发展。所以现在只需尝试调整。