"Hiding" overridden methods in Java

“隐藏”覆盖在Java方法

Tags: java override
标签: java override

问题 (Question)

Let's say I have some class

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

and another class extending it

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

And let's say that if you are using a FooExtension object, you really shouldn't be calling the foo(int number) method, but instead only use foo(String text).

It's not possible to override the foo(int number) method of the original class with a lower visibility since that breaks contract when I assign a FooExtension instance to a Foo variable.

Is there a way that is considered "good practice" to indicate that if you are using FooExtension, you really shouldn't be calling the original version of foo any more? Maybe overriding it and marking it deprecated? Or overriding it and having it throw an UnsupportedOperationException?

比方说我有一些课

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 ?

最佳答案 (Best Answer)

Is there a way that is considered "good practice" to indicate that if you are using FooExtension, you really shouldn't be calling the original version of foo any more? Maybe overriding it and marking it deprecated? Or overriding it and having it throw an UnsupportedOperationException?

It's hard to define a "good practice", when you are kind of starting with a "bad practice". If you are inheriting from a class, but you don't want some of the methods of the parent class, then you shouldn't be using inheritance at all!

Is it possible? Yes, it is possible to do what you want:

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());
    }
}

But I think designing something like this is bad. Users of your code would likely be surprised if they tried to call a method that belongs to the supertype and got an exception instead.

In cases like this, it is much better to use composition instead of inheritance. That way you can simply delegate only the calls you want, to your internal instance.

EDIT

Public inheritance is an "is a" relationship. So from the perspective of someone who is using your class, they would expect FooExtension to behave like Foo, except with some additional behavior. By doing what you are doing, you're violating that definition.

Another thing your design violates is the Liskov substitution principle. The principle says that if you have a subtype S of a type T, then replacing objects of type T with objects of type S should not alter the behavior of your program.

If one were to follow your design, replacing instances of Foo with FooExtension will cause your program to fail. This is why what you're trying to do is not really recommended.

有一种被认为是“好习惯”表明,如果您使用的是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());
    }
}

答案 (Answer) 2

This is not an override. It is an overload. Overloads hide the method they overload if the overloaded method is in a base class. This is a fundamental rule of Java and also of C++.

The answer to your question is therefore that it already happens.

这不是一个覆盖。它是一个过载。过载隐藏方法他们超载重载基类方法。这是一个Java和c++的基本规则。

你问题的答案是,它已经发生了。

本文翻译自StackoverFlow,英语好的童鞋可直接参考原文:http://stackoverflow.com/questions/22082658