Bei der Entwicklung in OOP wird manchmal eine Schnittstelle / ein Vertrag von einer Bibliothek vergeben, die Sie nicht ändern können. Nennen wir diese Schnittstelle J.
Jetzt haben Sie ein Objekt der Klasse A, das Objekte verwendet, die diese Schnittstelle implementieren. Innerhalb von A wird nur ein kleiner Teil der Definitionen der Schnittstelle benötigt. Einige der Objektklassen werden von mir während des Projekts erstellt (nennen wir eine von ihnen Typ D), daher ist die Implementierung von allem in Interface J mit einem Mehraufwand verbunden.
Ich möchte eine Teilmenge der Funktionalität in Schnittstelle J implementieren, aber meine bisherigen Lösungen erfüllen mich nicht:
- Das Implementieren jedes Aspekts von J und das anschließende Auslösen von "notImplementedExceptions" führt zu einer Fehlinformation des Benutzers meiner Objekte: Es scheint, dass meine Objekte vom Typ D der Schnittstelle J entsprechen, aber nicht - und andere Konsumenten meiner Objekte (die Objekte akzeptieren, die die Schnittstelle implementieren) J) kann mich nicht auf die Integrität meiner Objekte verlassen.
- Das Implementieren einer neu definierten Schnittstelle verbietet mir die Verwendung von Objekten, die nur die Schnittstelle J implementieren, obwohl die Schnittstelle J vollständig mit meiner eigenen Schnittstelle kompatibel ist.
- Wenn meine benutzerdefinierten Objekte die Schnittstelle J implementieren, würde dies einen erheblichen Overhead verursachen, da sie nicht alle diese Funktionen benötigen.
Wenn ich in der Lage wäre, die Schnittstelle J zu ändern, würde ich eine "Superschnittstelle" K erstellen, die diese Teilmenge der Funktionalität der Schnittstelle J aufweist, und die Schnittstelle J von der Schnittstelle K erben lassen. Aber ich kann die Schnittstelle J nicht ändern.
Was ist eine objektorientierte Lösung für dieses Problem? Implementiert die beste Lösung immer noch "nur" Interface J? Oder gibt es OOP-Möglichkeiten, ein Interface zu "überklassifizieren", ohne es zu verändern?
quelle
Antworten:
Wenn Sie die Schnittstelle J nicht steuern, stecken Sie fest.
Sie können aus Gründen der Übersichtlichkeit Ihre eigene Schnittstelle subJ und Schnittstelle J implementieren und subJ in Ihrem eigenen Code verwenden, um zu verdeutlichen, dass die zusätzlichen Methoden in Schnittstelle J nicht erforderlich sind, aber ich denke, das bringt Ihnen nicht viel
Wenn möglich, implementieren Sie die gesamte Schnittstelle J vollständig
Wenden Sie sich nach Möglichkeit an den Eigentümer von Schnittstelle J, und bitten Sie ihn, sie zu ändern, um sie besser an Ihre Zwecke anzupassen
quelle
Der springende Punkt bei der Implementierung einer Schnittstelle besteht darin, einen festen Vertrag zwischen dem Anrufer und dem Angerufenen herzustellen, der sich nie ändert, während die Implementierungsdetails variieren können.
Indem Sie die Schnittstelle J implementieren, teilen Sie der Außenwelt mit, was Sie tun können.
Wenn Sie nicht die Hälfte von dem benötigen, was J tut, sollten Sie entweder die Schnittstelle wirklich unterteilen, da sie nicht so klein ist, wie sie sein könnte, oder Sie müssen
NotImplementedException
die Methoden und Eigenschaften verwenden, die Sie nicht benötigen. Dies ist jedoch nicht die beste Lösung, da dadurch die Erwartungen der Benutzer an die Funktionsweise Ihres Codes gestört werden.quelle
Wenn Ihre Consumer-Klasse A nicht die gesamte Schnittstelle J benötigt, würde ich vorschlagen, eine neue Schnittstelle (nennen Sie sie K) zu erstellen, die alle erforderlichen Informationen ausführlich beschreibt.
Dies ist ein klares Signal für alle, die Klasse A verwenden, welche Vertragspartei sie haben. Dadurch verbessern sich die Wiederverwendungschancen. Wenn jemand ein Objekt bereitstellen muss, das eine große und komplexe Schnittstelle implementiert, um etwas relativ Einfaches zu tun, wird er wahrscheinlich das schreiben, was Klasse A selbst tut.
Damit Klasse A Objekte verwenden kann, die nur die Schnittstelle J implementieren, können Sie eine Wrapper-Klasse bereitstellen, die die Schnittstelle K implementiert und entsprechende Aufrufe an ein Mitglied der Schnittstelle J weiterleitet.
quelle
Obwohl ich den vorhandenen Antworten zustimme, die besagen, dass Sie J entweder vollständig (mit Ausnahmen für nicht implementierte Methoden) oder überhaupt nicht implementieren müssen, ist eine mögliche Problemumgehung folgende:
Bitte beachten Sie, dass dies eine ziemlich hässliche Lösung ist, da ein Wrapper erforderlich ist, der mehrere Dinge akzeptiert, die im Wesentlichen dasselbe sind. Aber es wird folgendes erreicht:
Wenn Ihre OO-Sprache keine anonyme Schnittstelleninstanziierung zulässt, können Sie eine Dummy-Implementierung der Schnittstelle erstellen und diese instanziieren.
quelle
Wie lange würde die Implementierung der gesamten Schnittstelle dauern?
Wenn Sie längere Zeit benötigen, deutet dies auf ein Designproblem hin, und ich rate Ihnen (wie Steven A. vor mir), sich mit dem Eigentümer in Verbindung zu setzen und zu prüfen, ob es in Zukunft geändert werden kann.
Verwenden Sie die Schnittstelle in Ihrem eigenen Code, unabhängig von der Bibliothek der Schnittstelle?
Wie von Steven A. vorgeschlagen, können Sie Ihre eigene Benutzeroberfläche so verwenden, wie Sie es in Ihrem eigenen Code sehen möchten. Dies hält zumindest Ihren Inhouse-Code sauber. Sie können dies auch an den Eigentümer als die zu erwartende Schnittstelle senden. Vielleicht stimmt er Ihnen zu, oder vielleicht kann er Ihnen erklären, warum die Schnittstelle nicht aufgeteilt werden sollte.
Würde Ihre Implementierung jemals die nicht verwendeten Mitglieder der Schnittstelle benötigen?
Falls Sie erwarten können, dass sie niemals aufgerufen werden, da sie nicht unterstützt werden, bevorzuge ich die
NotSupportedException
. Dies gibt einen klaren Hinweis darauf, dass Sie diese Schnittstelle niemals unterstützen werden, anstatt sie nicht zu implementieren.quelle
NotSupportedException
es zu verwenden, macht deutlich, dass Sie diese Methode nicht unterstützen.NotImplementedException
für Produktionscode, wo ich sonst schreiben würde "TODO: Implementiere dies" Leider werden sie nicht in der Aufgabenliste von Visual Studio angezeigt . Aber in der Praxis lasse ich kaum eine Methode länger als zwei Tage unimplementiert. Resharper zeigt diese Ausnahmen auch in Fettdruck an (zumindest bei meinem Setup). :)Implementieren Sie das, was Sie benötigen, und werfen Sie eine Ausnahme NoImplementedException auf die anderen.
Dies ist eine Frage der Verwendung. Wenn Sie die Schnittstelle nicht verwenden oder wissen, dass Ihr Code die Schnittstelle nicht verwendet, investieren Sie keine Zeit in diese, da Sie keine Zeit in redundanten Code investieren müssen.
Arbeiten Sie für die anstehende Aufgabe und behalten Sie die Übersicht, die andere Benutzer benötigen, wenn sie die Benutzeroberfläche verwenden möchten.
Viele Schnittstellen in Java sind nicht vollständig implementiert.
Dies ist der Apache-Ansatz für Dinge: http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/NotImplementedException.html
quelle