有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java强制调用专用方法

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

class Bar {}

class ExtendedBar extends Bar {}

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

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

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

当然,有一种简单的方法可以解决这个问题——我们只需要将doFoo重命名为其他名称——但是,如果不重命名该方法,就可以保持该方法的名称,因为它在强大的传统上下文中使用,这仍然让我们感到惊讶


共 (2) 个答案

  1. # 1 楼答案

    除了其他人说的话:为什么你在这里尝试。。。这完全是错误的

    定义继承层次结构需要更多的考虑,而不仅仅是在类上添加“扩展内容”。您要确保您理解Liskov Substitution Principle

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

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

  2. # 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将正确地解析方法调用并调用专门的方法调用