繁体   English   中英

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

[英]“Hiding” overridden methods in Java

假设我有一些课程

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)

由于在我将FooExtension实例分配给Foo变量时会破坏契约,因此无法覆盖具有较低可见性的原始类的foo(int number)方法。

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

有没有一种方法被认为是“良好做法”,表明如果你使用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替代原则 原理说如果你有一个类型为T的子类型S ,那么用类型S对象替换类型为T的对象不应该改变你的程序的行为。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM