2013-03-29 8 views
5

ich die folgende Hierarchie in Java haben:Aufschalten Methode in geerbten Schnittstelle mit dem Subtyp mit Generika

interface ObserverA {} 

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

Und ich will es so erweitern:

interface ObserverB extends ObserverA{} 

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

so dass die addObserver() Methode von B würde die gleiche Methode in A überschreiben. Da es nicht funktioniert, Implementierungen von B müssten beide Versionen von addObserver() implementieren, ich möchte nur eine haben.

Kann dies in einer klugen Weise geschehen, die nicht A wie parametrieren mit sich bringt:

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

hackish Lösungen sind herzlich willkommen!

+0

Generischer Typ ist immer ein besserer Weg für solche Dinge, wo Sie nicht wissen, der Typ – Biswajit

Antwort

1

Wie wäre es -

interface ObserverA {} 

interface A { 

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

und -

interface ObserverB extends ObserverA{} 

interface B extends A{ 

    // do nothing, or omit this interface entirely. 

} 

, so dass Sie in der Lage sein werden, jede Art zu übergeben, die ObserverA als Argument an die addObserver Methode erbt.

Wenn Sie nach einer kleinen Erklärung suchen, dann lesen Sie weiter.

Ich habe die Methode in der ersten Schnittstelle geändert, Bounded Type Parameter zu verwenden. Die Art, wie es deklariert ist, erlaubt es, beliebige Objekte als Argument an die addObserver-Methode zu übergeben, solange es sich um den Typ ObserverA handelt, oder er erbt von ObserverA. Da Ihre ObserverB von ObserverA erbt, können Sie problemlos Objekte der beiden Typen ObserverA und ObserverB als Argument an diese Methode übergeben.

EDIT

Von Ihrer Klarstellung scheint es, dass Sie zwei verschiedene Schnittstellen zwischen ihnen ohne hierarchische Beziehung schaffen sollte. Sie scheinen nicht verwandt zu sein, weil Sie Implementierungen nur für die zweite Methode bereitstellen und gleichzeitig die erste vermeiden möchten. Anstatt sich selbst dazu zu zwingen, die Implementierung für die Methode von der ersten Schnittstelle aus bereitzustellen, sollten Sie sie trennen. Dazu gibt es auch ein OOP-Prinzip - Interface Segregation Principle.

+0

Ich habe das schon versucht, das Problem ist, dass 'B' akzeptieren würde' 'und ich will es nur akzeptieren 'ObserverB' (oder' 'in der Tat) – Chirlo

+0

@Chirlo: Siehe meine Bearbeitung. –

+0

Das Beispiel, das ich gab, ist eine vereinfachte Version von dem, was ich tun möchte. "A" wäre eine komplexere Schnittstelle, die "B" erweitern müsste, aber seine Beobachter sind auch komplexer als die von "A". Ich habe die Frage bearbeitet, um die Tatsache widerzuspiegeln, dass "B" die Funktionalität von "A" erweitert. – Chirlo

2

Obwohl Ihr Beispiel etwas anderes zeigt, möchten Sie wahrscheinlich eine generische Schnittstelle implementieren, die von verschiedenen Klassen implementiert wird. Werfen Sie einen Blick auf diese:

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

Wie Sie sehen können sowohl Ersten und Zweiten Klassen die gleiche Schnittstelle implementieren, aber mit unterschiedlichen Parametern. Sie parametrisieren die implementierte Schnittstelle mit sich selbst, aber anstatt Observer<Frist> zu schreiben, könnten Sie Observer<Integer> oder was auch immer Sie möchten schreiben.

EDIT

Unter Berücksichtigung Ihrer Präzisierungen dies eine generische Implementierung des Codes innerhalb der Schnittstelle Hierarchie würde Ihnen präsentiert.

interface ObserverA {} 

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

interface ObserverB extends ObserverA {} 

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

Sie können Methodenparametertypen in Subschnittstellen oder Subklassen nicht eingrenzen. Sie können sie nur erweitern, da Implementierungen des Subtyps in der Lage sein müssen, den Vertrag des Supertyps zu erfüllen.

Ebenso können Sie Rückgabetypen und Ausnahmen eingrenzen, aber nicht erweitern, aus dem gleichen Grund.

Verwandte Themen