2009-04-08 5 views
3

Ich habe eine Hierarchie von drei Schnittstellen, Großeltern, Eltern und Kind. Eltern und Kind haben eine Methode "hinzufügen", die verschiedene Eingabeparameter im Kind erfordert. Während es kein Problem ist, die erforderliche Signatur im Kind hinzuzufügen, wird die geerbte Methode sinnlos sein, also gibt es eine Möglichkeit, es überhaupt nicht dort zu haben? Die anderen Methoden funktionieren gut.Wie kann ich in einer Java-Schnittstelle * eine * bestimmte Methode verwenden, die von einer übergeordneten Schnittstelle geerbt wurde?

Vielleicht, zu erreichen, was ich will, ich völlig das Design verbessern, so dass ich kurz umreißen, was die Schnittstellen zu:

I Zählerstände zu sammeln, die von einer Zeit und einem Wert bestehen. Die Großmutter-Schnittstelle ist für eine einzige Lesung. Ich habe auch Klassen, die eine Reihe von aufeinanderfolgenden Lesungen (eine Serie) darstellen, und eine, die mehrere Serien enthält, die über den gleichen Zeitraum laufen (nennen wir das einfach eine Tabelle).

Die Tabelle kann als eine Reihe betrachtet werden (die die Werte orthogonal zur Zeitachse aggregiert), und sowohl Tabelle als auch Reihe können als eine einzige Lesung betrachtet werden (die Implementierungen bieten unterschiedliche Aggregationsmöglichkeiten), daher die Vererbung. Dies scheint gut zu funktionieren, aber für die Add-Methode. (Ich kann der Serie einen einzelnen Punkt hinzufügen, aber für die Tabelle brauche ich einen zusätzlichen Parameter, der mir sagt, zu welcher Serie er gehört.)

Antwort

6

Vielleicht wäre es sinnvoll, die Schnittstellenvererbung alle zusammen zu brechen. Haben Sie nur spezifische Schnittstellen für bestimmte Arten von Verhaltensweisen. Welche Klassen Sie auch haben, die diese Schnittstellen implementieren, Sie können nur diejenigen auswählen, die sinnvoll sind, und müssen sich keine Gedanken über die Implementierung von Methoden machen, die keinen Sinn ergeben.

0

Eine Schnittstelle ist ein Vertrag. Es bedeutet, dass alles, was diese Schnittstelle implementiert, notwendigerweise die definierten Methoden implementiert. Sie könnten es technisch einfach als Dummy-Methode implementieren (kein Körper, einfach zurückgeben, was auch immer), aber meines Wissens muss es implementiert werden.

9

Nein, Sie können nicht vermeiden, eine Methode zu erben, da dies die Liskov substitution principle verletzen würde.

In der Praxis könnten Sie Implementierungen werfen UnsupportedOperationException, aber das wäre ziemlich böse.

Können Sie die geerbte Methode nicht mit einer Art Standardwert für die Serie implementieren?

+0

+1 für die endgültige Antwort auf, warum dies nicht funktioniert wie Schnittstellen. Ich stimme zu, dass das Auslösen von Ausnahmen bei jemandem, der versucht, sich entsprechend dem Vertrag zu verhalten, hässlich ist. Ich werde Andy Whites Vorschlag für eine Lösung prüfen. –

0

Sie können jederzeit das Verfahren als leer, zum Beispiel implementieren:

class A implements B{ void add(A) { /*Goes Nowhere Does Nothing*/ return;} } 

aber wirklich, es ist keine gute Idee. Eine bessere Lösung wäre, dass alle Ihre Großeltern, Eltern und Kinder alle dieselbe Klasse mit zwei zusätzlichen Methoden haben - hasParent(): boolean und hasChild(): boolean. Dies hat den Vorteil, dass es eine likov Ersatz-kompatible Änderung sowie ein saubereres Design ist.

4

Das Problem mit der Vererbung ist, dass der Fokus auf den Sprachmechanismus Menschen dazu bringt, eher über Implementierung als über Semantik nachzudenken.

Wenn B von A erbt, bedeutet dies, dass jede Instanz von B auch eine Instanz von A ist. In OOP bedeutet eine Instanz von etwas, dass Sie eine vernünftige Antwort auf ihre Methoden haben und zumindest ihre Nachrichten unterstützen .

Wenn Sie das Gefühl, dass B nicht eine der Botschaften von A unterstützen soll, dann soweit ich betroffen sind Sie haben zwei Möglichkeiten:

BAD - Werfen Sie eine „Nicht implementiert“ Ausnahme, wie Sie mit den Sammlungen erhalten würden Rahmen. Dies ist jedoch meiner Meinung nach eine schlechte Form.

Gut - Akzeptieren Sie, dass B kein Typ von A ist und vermeiden Sie die Vererbung, oder restrukturieren Sie es (z. B. mit Komposition und/oder Schnittstellen), so dass Sie den Code nicht neu schreiben müssen, aber Sie nicht verwenden Untertyp-Beziehung. Wenn Ihre Anwendung im Laufe der Zeit bestehen wird, möchten Sie keine semantischen Probleme in Ihren Hierarchien haben.

+0

+1 für gut. Soweit ich deine Frage verstehe, Hanno, besser, Zusammensetzung statt Vererbung zu verwenden. Weitere Details finden Sie hier: http://c2.com/cgi/wiki?UseCompositionAndInterfacesWithoutClassInheritance – Olivier

1

Danke, dass Sie mich auf den richtigen Weg gebracht haben, ich habe die Posts, die ich am hilfreichsten fand, updated. Da meine Lösung von den Beiträgen inspiriert wurde, aber nicht gepostet wird, teile ich mit, was ich mir vorgenommen habe:

Da die Hierarchie davon inspiriert war, wie die Daten angesehen werden sollten,, während sich die Probleme auf die Semantik beziehen Wie Sie hinzufügen Daten, ich werde die Schnittstellen für die Serie und Tabelle in eine Lese-und eine Schreibschnittstelle jeweils aufteilen. Die Schreibschnittstellen haben nichts miteinander zu tun, und die Leseschnittstellen können ohne Konflikte erben.

Ich werde dieses Wiki machen, falls jemand dies erweitern möchte.

1

Sie könnten den Code Refused Bequest Code suchen.

+0

+1 für den Link, scheint die Website für einige klassische Szenarien ziemlich nützlich. –

+0

Ich mag Code-Gerüche (gut, die Idee - nicht die Gerüche selbst) - es ist oft einfacher zu zeigen, was falsch ist, als eine theoretische Debatte darüber zu führen, was gut ist. – ptyx

Verwandte Themen