强制调用专用方法

时间:2016-04-27 12:14:42

标签: java

我们今天在工作中有一个有趣的角落案例,关于Java中的方法调用。想象一下:

class Bar {}

class ExtendedBar extends Bar {}

class Foo {
   void doFoo(Bar bar) {}
}

class ExtendedFoo extends Foo {
   void doFoo(ExtendedBar exBar) {}
}

现在您有ExtendedBar的实例,并且想要在doFoo()的实例上调用ExtendedFoo。在我们的测试中,运行时从Foo选择了doFoo(Bar)doFoo(ExtendedBar)实现,而不是ExtendedFoo

当然有一个简单的方法可以解决这个问题 - 我们只需要将doFoo重命名为其他内容 - 但是,如果不重命名方法,保留方法的名称,它会让我们感到震惊因为它在这里用于强大的传统环境中。

2 个答案:

答案 0 :(得分:2)

我认为没有办法直接做到这一点,因为你不是重写方法,而是着色它。您可以通过在其上添加@Override来轻松断言。请注意,如果您使用返回类型执行此操作,它将正常工作:

class Foo {
    Bar doFoo() { return null; }
}

class ExtendedFoo extends Foo {
    @Override
    ExtendedBar doFoo() { return null; }
}

但只要您更改参数,就会有不同的签名

在这种情况下你可以做的是使用通用性我想。

class Foo<BAR extends Bar> {
    void doFoo(BAR bar) {}
}

class ExtendedFoo extends Foo<ExtendedBar> {
    @Override
    void doFoo(ExtendedBar exBar) {}
}

现在因为你实际上正确覆盖方法,JRE将正确解析方法调用并调用专用方法。

答案 1 :(得分:0)

除了别人说的话:为什么你在这里尝试......简直就是错误。

定义继承层次结构需要更多考虑,而不仅仅是在类上添加“extends Something”。您希望确保理解Liskov Substitution Principle

在您的情况下:子类应该从不 限制某些基类中定义的任何参数类型的方法。您可以限制返回类型(例如,当基类返回Number时返回Long);但对于“输入”参数,只能加宽(允许数字,当基类使用Long时)。

正确的OO建模的想法意味着:在任何使用Foo对象的源代码中......您应该能够用Foo替换ExtendedFoo个对象宾语。你的提议违反了这条规则。