简体   繁体   中英

“Hiding” overridden methods in Java

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 ?

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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