在Java中“隐藏”重写的方法

时间:2014-02-27 23:07:51

标签: java override

假设我有一些课

public class Foo {
    public void foo(int number) {
        // Do some foo-ing of the given number
    }
}

和另一个扩展它的类

public class FooExtension extends Foo {
    public void foo(String text) {
        super.foo(text.length());
    }
}

让我们说如果您使用的是FooExtension对象,那么您真的不应该调用foo(int number)方法,而应该只使用foo(String text)

由于在我将foo(int number)实例分配给FooExtension变量时违反了合同,因此无法覆盖原始类的Foo方法,因为该方法具有较低的可见性。

有没有一种方法被认为是“良好做法”,表明如果您使用的是FooExtension,那么您真的不应该再调用foo的原始版本了吗?也许压倒它并标记它已被弃用?或者覆盖它并让它抛出UnsupportedOperationException

2 个答案:

答案 0 :(得分:2)

  

有没有一种方法被认为是“良好做法”,表明如果你使用的是FooExtension,你真的不应该再调用原始版本的foo了吗?也许压倒它并标记它已被弃用?或者覆盖它并让它抛出UnsupportedOperationException?

当你开始采用“不良做法”时,很难定义一个“良好做法”。如果您继承自某个类,但想要父类的某些方法,那么您根本不应该使用继承!

有可能吗?是的,可以做你想做的事:

public class FooExtension extends Foo {

    @Override
    public void foo(int number) {
        throw new UsupportedOperationException("Operation is not supported");
    }

    public void foo(String text) {
        super.foo(text.length());
    }
}

但我觉得设计这样的东西很糟糕。如果他们试图调用属于超类型的方法并获得异常,则代码的用户可能会感到惊讶。

在这种情况下,使用组合而不是继承更好。这样,您只需将所需的调用委托给内部实例。

修改

公共继承是一种“是一种”关系。因此,从使用您的课程的人的角度来看,他们希望FooExtension的行为类似于Foo,除了一些额外的行为。通过做你正在做的事情,你违反了这个定义。

您的设计违反的另一件事是Liskov substitution principle。原则说如果你有类型S的子类型T,那么用T类型的对象替换类型S的对象不应该改变你的程序的行为

如果要遵循您的设计,将Foo的实例替换为FooExtension将导致您的程序失败。这就是为什么你不想做的事情。

答案 1 :(得分:0)

这不是覆盖。这是一个过载。如果重载方法在基类中,则重载会隐藏它们重载的方法。这是Java和C ++的基本规则。

因此,您的问题的答案已经发生。