Override method in inherited interface with subtyp

2020-07-14 05:31发布

问题:

I have the following hierarchy in java:

interface ObserverA {}

interface A {
  void method1();
  addObserver(Observer o);
}

And I want to extend it like this:

interface ObserverB extends ObserverA{}

interface B extends A {
   void method2();
   addObserver(ObserverB  o);
}

in such a way that the addObserver() method of B would override the same method in A. As it is it doesn't work, implementations of B would need to implement both versions of addObserver(), I wan't to have just one.

Can this be done in a clever way that doesn't involve having to parameterize A like:

interface A<O extends Observer> { 
    addObserver(O o);
}

Hackish solutions are most welcome!

回答1:

You can't narrow method parameter types in subinterfaces or subclasses. You can only broaden them, since implementations of the subtype must be able to fulfill the contract of the supertype.

Similarly, you can narrow return types and exceptions, but not broaden them, for the same reason.



回答2:

Although your example shows something different I suppose you would like to achive a generic interface implemented by different classes. Have a look at this:

public interface Observer<T> {
    void addObserver(T t);
}

public class First implements Observer<First> {
    @Override
    public void addObserver(First t) {
    }
}

public class Second implements Observer<Second> {
    @Override
    public void addObserver(Second t) {
    }
}

As you can see both First and Second classes implement the same interface but with different types of parameters. They parametrize the implemented interface with themselved, but instead of writing Observer<Frist> you could write Observer<Integer> or whatever you would like.

EDIT

Taking into account your clarifications this would be a generic implementation of your code within the interface hierarchy you presented.

interface ObserverA {}

interface A<T> {
    void method1();
    void addObserver(T o);
}

interface ObserverB extends ObserverA {}

interface B extends A<ObserverB> {
    void method2();
}


回答3:

How about -

interface ObserverA {}

interface A {

    <T extends ObserverA> void addObserver(T o);
}

and -

interface ObserverB extends ObserverA{}

interface B extends A{

    // do nothing, or omit this interface entirely.

}

so that you'll be able to pass any type that inherits ObserverA as argument to the addObserver method.

If you are looking for a little explanation, then read on.

I have changed the method in the first interface to use Bounded Type Parameter. The way it's declared, it will allow any objects to be passed as argument to the addObserver method as long as it's type is ObserverA, or it inherits from ObserverA. Since your ObserverB is inheriting from ObserverA, you can safely pass objects of both ObserverA and ObserverB types to this method as argument.

EDIT

From your clarification, it seems that you should create two different interfaces without any hierarchical relationship between them. They seem to be unrelated because you want to provide implementations for only the second method, while avoiding the first one. So, rather than forcing yourself to provide the implementation for the method from the first interface, you should separate them. There is also an OOP principle for this - Interface Segregation Principle.