2013-03-29 3 views
5

я следующую иерархию в Java:Override в унаследованной интерфейс с подтипом с дженериков

interface ObserverA {} 

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

И я хочу выразить это так:

interface ObserverB extends ObserverA{} 

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

таким образом, что addObserver() метод B переопределяет тот же метод в A. Как бы то ни было, реализации B потребуется реализовать обе версии addObserver(), у меня не будет только одного.

Может ли это быть сделано умным способом, который не подразумевает наличия спараметрировать A как:

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

хак решение приветствуется!

+0

Общий тип всегда является лучшим способом для выполнения такой задачи, когда вы не знаете тип – Biswajit

ответ

1

Как насчет -

interface ObserverA {} 

interface A { 

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

и -

interface ObserverB extends ObserverA{} 

interface B extends A{ 

    // do nothing, or omit this interface entirely. 

} 

так, что вы будете иметь возможность передавать любой тип, который наследует ObserverA в качестве аргумента метода addObserver.

Если вы ищете небольшое объяснение, то читайте дальше.

Я изменил метод в первом интерфейсе для использования Bounded Type Parameter. Способ, которым он объявлен, позволяет передавать любые объекты в качестве аргумента в метод addObserver, если он имеет тип ObserverA или наследуется от ObserverA. Так как ваш ObserverB наследует от ObserverA, вы можете безопасно передавать объекты как ObserverA, так и ObserverB типам для этого метода в качестве аргумента.

EDIT

Из вашего разъяснения, кажется, что вы должны создать два различных интерфейса без каких-либо иерархических отношений между ними. Они кажутся несвязанными, потому что вы хотите обеспечить реализацию только для второго метода, избегая при этом первого. Таким образом, вместо того, чтобы заставить себя обеспечить реализацию метода из первого интерфейса, вы должны их разделить. Для этого также существует принцип ООП - Interface Segregation Principle.

+0

Я уже пробовал это, проблема в том, что 'B' будет принимать любые' ', и я хочу, чтобы он принимал 'ObserverB' (или' ', если на то пошло) – Chirlo

+0

@Chirlo: См. Мое редактирование. –

+0

Пример, который я дал, - это упрощенная версия того, что я хочу сделать. 'A' будет более сложным интерфейсом, который' B' должен расширить, но его наблюдатели также более сложны, чем те, что от 'A'. Я отредактировал вопрос, чтобы отразить тот факт, что «B» расширяет функциональность от «A» – Chirlo

2

Хотя ваш пример показывает что-то другое, я полагаю, вы хотели бы получить общий интерфейс, реализованный разными классами. Посмотрите на это:

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) { 
    } 
} 

Как вы можете видеть, как первый, так и второй классы реализуют один и тот же интерфейс, но с различными типами параметров. Они параметризуют реализованный интерфейс с themselved, но вместо того, чтобы писать Observer<Frist>, вы можете написать Observer<Integer> или что бы вы ни хотели.

EDIT

Принимая во внимание ваших разъяснений, что это будет общая реализация коды в иерархии интерфейса вы представили.

interface ObserverA {} 

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

interface ObserverB extends ObserverA {} 

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

Вы не можете сузить типы параметров метода в подинтерфейсах или подклассах. Их можно только расширить, поскольку реализации подтипа должны быть в состоянии выполнить контракт супертипа.

Аналогичным образом, вы можете сузить типы и исключения возврата, но не расширять их по той же причине.