2013-03-29 10 views
5

Mam następującą hierarchię w Java:Zastąp w odziedziczonej interfejs z podtypu z rodzajowych

interface ObserverA {} 

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

I chcę przedłużyć go tak:

interface ObserverB extends ObserverA{} 

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

w taki sposób, że addObserver() metoda B zastąpi tę samą metodę w A. Ponieważ to nie działa, implementacje B wymagałyby implementacji obu wersji addObserver(), nie będę miał ich.

Można to zrobić w sprytny sposób, że nie wymaga konieczności parametryzacji A jak:

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

hackish rozwiązania są jak najbardziej mile widziane!

+0

Typ ogólny jest zawsze lepszym sposobem na zrobienie czegoś takiego, gdy nie znamy typu – Biswajit

Odpowiedz

1

Jak o -

interface ObserverA {} 

interface A { 

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

i -

interface ObserverB extends ObserverA{} 

interface B extends A{ 

    // do nothing, or omit this interface entirely. 

} 

tak, że będziesz w stanie przekazać wszelkiego rodzaju, która dziedziczy ObserverA jako argument do metody addObserver.

Jeśli szukasz wyjaśnienia, czytaj dalej.

Zmieniłem metodę w pierwszym interfejsie, aby użyć Bounded Type Parameter. Sposób, w jaki jest zadeklarowany, umożliwi przekazywanie dowolnych obiektów jako argumentów do metody addObserver, o ile jest to typ ObserverA, lub dziedziczy po ObserverA. Ponieważ twój ObserverB dziedziczy po ObserverA, możesz bezpiecznie przekazywać obiekty z obu typów ObserverA i ObserverB do tej metody jako argument.

EDIT

ze swojego wyjaśnienia, wydaje się, że należy utworzyć dwa różne interfejsy bez hierarchicznej relacji między nimi. Wydaje się, że nie mają ze sobą związku, ponieważ chcesz zapewnić implementacje tylko dla drugiej metody, unikając pierwszej. Zamiast zmuszać się do implementacji metody z pierwszego interfejsu, należy je rozdzielić. Istnieje również zasada OOP - Interface Segregation Principle.

+0

Próbowałem już tego, problem polega na tym, że 'B' akceptuje dowolne' 'i chcę, żeby akceptował tylko 'ObserverB' (lub' 'o to chodzi) – Chirlo

+0

@Chirlo: Zobacz moją edycję. –

+0

Podałem przykład uproszczonej wersji tego, co chcę zrobić. 'A' będzie bardziej złożonym interfejsem, który' B' musi rozciągnąć, ale jego obserwatorzy są również bardziej skomplikowani niż te z 'A'. Zmieniłem to pytanie, aby odzwierciedlić fakt, że "B" rozszerza funkcjonalność z "A" – Chirlo

2

Chociaż twój przykład pokazuje coś innego Przypuszczam, że chciałbyś osiągnąć ogólny interfejs implementowany przez różne klasy. Spójrz na to:

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

Jak widać zarówno pierwsza i druga klasa implementują ten sam interfejs, ale z różnymi typami parametrów. Parametryzują zaimplementowany interfejs z nimi, ale zamiast pisać Observer<Frist> możesz napisać Observer<Integer> lub cokolwiek chcesz.

EDIT

Uwzględniając swoje wyjaśnienia byłoby to generic implementacja kodu w hierarchii interfejsu Ci przedstawione.

4

Nie można zawężać typów parametrów metod w podinterfejsach lub podklasach. Możesz je tylko poszerzyć, ponieważ implementacje podtypu muszą być w stanie spełnić umowę supertypu.

Podobnie można zawęzić typy i wyjątki powrotu, ale nie poszerzyć ich z tego samego powodu.