Schnittstelle vs-Basisklasse
Wann sollte ich ein interface und Wann soll ich eine base-Klasse?
Sollte es immer eine Schnittstelle, wenn ich nicht wollen, um tatsächlich zu definieren, die eine Basis-Implementierung der Methoden?
Wenn ich einen Hund habe und Katzen-Klasse. Warum möchte ich zu implementieren IPet statt PetBase? Ich kann verstehen, dass Schnittstellen für ISheds oder IBarks (IMakesNoise?), weil diejenigen, die platziert werden kann auf einem pet von pet-basis, aber ich verstehe nicht, was für ein generisches Pet.
Nur ein Punkt, ich denke, Sie sollten berücksichtigen, - Schnittstellen haben kann, stellen einige Grenzen, die Sie möglicherweise nicht bewusst sein, bis in sehr späten Phasen. Zum Beispiel, mit .NET kann man nicht serialisieren eines interface-member-variable, also, wenn Sie einen Klasse Zoo und eine member-variable array von IAnimals Sie werden nicht in der Lage zu serialisieren Zoo (und das heißt schreiben, WebServices oder anderer Dinge, die eine Serialisierung würde ein Schmerz sein).
Diese Frage könnte helfen zu verstehen, Konzept der Schnittstellen. stackoverflow.com/q/8531292/1055241
Diese Frage könnte helfen zu verstehen, Konzept der Schnittstellen. stackoverflow.com/q/8531292/1055241
InformationsquelleAutor |
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nehmen wir dein Beispiel, ein Hund und eine Katze sind Klasse, und lassen Sie uns zeigen, mit C#:
Beide einen Hund und eine Katze sind Tiere, die speziell Vierbeiner Säugetiere (Tiere sind waaay zu allgemein). Lassen Sie uns annehmen, dass Sie eine abstrakte Klasse Säugetier ist, für beide von Ihnen:
Diese Basisklasse wird wahrscheinlich Standard Methoden wie:
Alle Verhalten, haben mehr oder weniger die gleiche Implementierung zwischen den beiden Tierarten. Um zu definieren, diese müssen Sie:
Nun nehmen wir an, es gibt auch andere Tiere, die wir normalerweise sehen, in einem zoo:
Dieser noch gültig sein, weil der Kern der Funktionalität
Feed()
undMate()
werden immer noch die gleichen.Jedoch, Giraffen, Nashörner und Flusspferde sind nicht gerade Tiere, die Sie machen können Tiere aus. Das ist, wo eine Schnittstelle wird für Sie nützlich sein:
Die Umsetzung für den oben genannten Vertrag wird nicht gleich sein, zwischen einer Katze und Hund; indem Sie Ihre Implementationen einer abstrakten Klasse zu Erben, wird es eine schlechte Idee ist.
Ihren Hund und Katze-Definitionen sollte jetzt so Aussehen:
Theoretisch können Sie diese überschreiben, von einer höheren Basis-Klasse, aber im wesentlichen eine Schnittstelle ermöglicht Ihnen das hinzufügen nur auf die Dinge, die Sie benötigen, in eine Klasse ohne die Notwendigkeit für die Vererbung.
Folglich da Sie kann in der Regel nur Erben von einer abstrakten Klasse (in den meisten statisch typisierten OO-Sprachen,... Ausnahmen gibt es in C++), aber in der Lage sein, um mehrere Schnittstellen zu implementieren, die es ermöglicht das konstruieren von Objekten in einer streng als erforderlich basis.
Die Schnittstelle ist ein Vertrag. Sie sind, dass nur der Teil des Vertrages, die einen service erfordert. Wenn Sie eine 'PettingZoo', Sie sicherlich don ' T wollen setzen 'Kumpel'-ing, um den Benutzer!
Touche, obwohl ich Tat es, um besser zu veranschaulichen was ein interface ist und was eine abstrakte Klasse ist für das vis-a-vis seinem Verständnis. Ein Hund und eine Katze, die nicht angezeigt wird, um eine starre Anforderung!
Es sollte angemerkt werden, dass in der Auslegung, die JIT-ing-Umgebungen (insbesondere die JVM), virtuelle Methodenaufrufe sind deutlich schneller als interface-Methode aufrufen, abhängig von dem Kontext. Ich betone "Kontext", weil die JVM kann oft optimieren Sie Weg, die langsame Methode-lookups. (z.B., wenn eine Liste von interface Erben neigen dazu, Instanzen der gleichen Klasse. Dieses leider macht das benchmarking ein bisschen schwierig.) Wenn Sie versuchen, etwas zu optimieren die Leistung empfindlich, und nur dann, sollten Sie dies berücksichtigen.
Auch, eine Schnittstelle erlaubt eine pet-rock, so dass es gebadet zu werden und gelehrt werden tricks, aber Fütterung und Paarung würde nicht unterstützt werden, denn das wäre lächerlich für einen rock.
InformationsquelleAutor
Gut, Josh Bloch selbst sagte in Effektive Java-2d:
Lieber über Schnittstellen abstrakte Klassen
Einige der wichtigsten Punkte:
Auf der anderen Seite, Schnittstellen sind sehr schwer zu entwickeln. Wenn Sie eine Methode hinzufügen, um eine Schnittstelle, es werde brechen alle it-Implementierungen.
PS.: Kaufen Sie das Buch. Es ist viel detaillierter.
wir haben "Interface-Segregation-Prinzip". Dieses Prinzip lehrt uns, darauf zu achten, wie wir schreiben unsere Schnittstellen.Wann schreiben wir unsere Schnittstellen sollten wir hinzufügen, nur Methoden, die es sein sollte. Wenn wir die add-Methoden, die nicht da sein sollte, die Klassen, die das interface implementieren müssen, um diese Methoden als gut. Zum Beispiel, wenn wir eine Schnittstelle namens Arbeiter und fügen Sie eine Methode Mittagspause, die alle Mitarbeiter haben, um es zu implementieren. Was, wenn der Arbeiter einen Roboter?Als Fazit Schnittstellen mit Methoden, die nicht spezifisch für Sie sind aufgerufen, verschmutzt oder Fett-Schnittstellen.
Seit Java 8, Standard-Methoden ermöglichen das hinzufügen neuer Funktionen der Schnittstellen und Sicherstellung der Abwärtskompatibilität für bestehende Klassen implementieren diese Schnittstelle. Default-Methoden aufgerufen werden standardmäßig, wenn Sie nicht überschrieben sind in der implementierenden Klasse. Alle implementierenden Klasse können entweder überschreiben default-Methoden, oder Sie können direkt rufen Sie die Instanz.defaultMethod()
InformationsquelleAutor
Modernen Stil zu definieren IPet und PetBase.
Den Vorteil der Schnittstelle ist, dass andere Codes können es verwenden, ohne Bindungen jeglicher Art zu anderen ausführbaren code. Komplett "sauber." Auch die Schnittstellen gemischt werden können.
Aber base-Klassen sind nützlich, um einfache Implementierungen und gemeinsame Dienstprogramme. So stellen Sie eine abstrakte Basisklasse, als auch, um Zeit zu sparen und den code.
yup yup! Und mit modernen IDE ' s wird es sogar schreiben die boiler-plate-code für Sie (und einige Sprachen gar nicht brauchen)
Eine Schnittstelle legt fest, wie die anderen Klassen können mit Ihrem code. Eine Basis-Klasse können Entwickler zur Implementierung der Schnittstelle. Zwei verschiedene Dinge, die für zwei unterschiedliche Zwecke.
Es ist nichts "modernes" hier. Basisklasse und interface mit der selben API ist einfach überflüssig. Sie können diesen Ansatz verwenden es in einigen Fällen, aber man sollte nicht verallgemeinern!
Die meisten unterstützten Kommentar zu die zweite unterstützte Antwort eigentlich nicht einverstanden ist mit der Antwort selbst, interessant. Ich muss sagen, ich sehe viele Beispiele von interface-und base-class co-existieren. In diesem Sinne ist es die "moderne" Art und Weise. Zum Beispiel, in MVVM-Muster, es ist eigentlich ViewModelBase-Klasse, die INotifyPropertyChanged implementiert. Aber wenn mein Kollege mich gefragt, warum habe ich die base-Klasse, statt der Implementierung der Schnittstelle in jedem view-Modell, ich weiß nicht, wie um ihn zu überzeugen
InformationsquelleAutor
Schnittstellen und Basisklassen repräsentieren zwei unterschiedliche Formen von Beziehungen.
Vererbung (Basis-Klassen) repräsentieren eine "ist-ein" - Beziehung. E. g. ein Hund oder eine Katze "ist-ein" Haustier. Diese Beziehung stellt immer die (einzige) Zweck der Klasse (in Verbindung mit der "das Prinzip der einzigen Verantwortung").
Schnittstellen, auf der anderen Seite, die zusätzliche Funktionen einer Klasse. Würde ich es nennen, eine "ist" - Beziehung, wie in "
Foo
ist Einweg", daher derIDisposable
Schnittstelle in C#.+1 schönes konzeptionelle Ansicht
Jemand sagte mir einmal eine Schnittstelle, wenn es eine "hat-ein" Beziehung. Ich bin mir nicht sicher, ob das immer wahr, wenn; Mein laptop hat einen Bildschirm, so sollten laptop implementieren, IScreen, oder eine Bildschirm-Eigenschaft? Letzteres scheint natürlicher zu mir.
komisch, dass Sie schreiben, dass, weil die Bildschirme sind implementiert, die über Schnittstellen für VGA, HDMI etc
"Kann sein" ist besser
InformationsquelleAutor
Schnittstellen
Basisklassen
es sei denn, die neue Methode ist eine abstrakte 🙂
InformationsquelleAutor
In der Regel sollten Sie zugunsten Schnittstellen über abstrakte Klassen. Ein Grund für die Verwendung einer abstrakten Klasse ist, wenn Sie gemeinsame Umsetzung unter den konkreten Klassen. Natürlich sollten Sie immer noch deklarieren Sie eine Schnittstelle (IPet) und eine abstrakte Klasse (PetBase) implementieren Sie dieses interface.Mit kleinen, distinct Schnittstellen, die Sie verwenden können, um ein Vielfaches weiter zu verbessern Flexibilität. Schnittstellen ermöglichen es, die maximale Menge an Flexibilität und Mobilität der Arten, über die Grenzen hinweg. Bei der übergabe von Referenzen über die Grenzen hinweg, immer direkt an der Schnittstelle und nicht den konkreten Typ. Dies ermöglicht es dem Empfänger, um zu bestimmen, konkrete Umsetzung und bietet Ihnen maximale Flexibilität. Das ist absolut wahr, wenn die Programmierung in einem TDD/BDD Mode.
Gang der Vier erklärt in Ihrem Buch "Weil die Vererbung stellt eine Unterklasse, die details der übergeordneten Umsetzung, es wird oft gesagt, dass 'Vererbung bricht Kapselung". Ich glaube dies um wahr zu sein.
Niemand hat gesagt, dass Ihre Schnittstellen müssen riesig sein. Kleinere, mehrere Schnittstellen und reichere Basis-Klassen, die eine große API.
Ist es nur mich oder tun, die meisten "Gemeine Arbeiter" - Klassen, die eine gemeinsame Umsetzung? In diesem Zusammenhang geht es gegen Ihre Regel der Begünstigung Schnittstellen. Ich würde noch einmal Ihre Verallgemeinerung in 2 Verallgemeinerungen: Die gemeinsamen Klassen, die enthalten kein oder wenig Logik sollte eine Schnittstelle implementieren. Diese gemeinsamen Klassen, die eine "anständige" Menge von Logik abgeleitet wird, sollte von einer Basis-Klasse (weil die meisten wahrscheinlich werden Sie die share-Funktion).
erlauben die maximale Menge an Flexibilität und Mobilität der Arten, über die Grenzen hinweg" bitte erläutern Sie diese Aussage.
InformationsquelleAutor
Dies ist ziemlich .NET-spezifisch, aber die Framework Design Guidelines Buch argumentiert, dass in Allgemeinen Klassen geben mehr Flexibilität in einem sich verändernden Rahmen. Sobald eine Schnittstelle versendet wird, erhalten Sie nicht die chance, es zu ändern, ohne zu brechen-code verwendet die Schnittstelle. Mit einem Klasse-aber Sie können es ändern und nicht brechen-code, der links zu. So lange Sie die richtigen änderungen, die beinhaltet das hinzufügen von neuen Funktionen, werden Sie in der Lage, zu erweitern und entwickeln Sie Ihre code.
Krzysztof Cwalina, sagt auf Seite 81:
That being said-es gibt sicherlich einen Platz für Schnittstellen. Als Allgemeine Richtlinie immer eine abstrakte Basisklasse, die die Implementierung einer Schnittstelle, wenn für nichts anderes als ein Beispiel für eine Möglichkeit, die das interface implementieren. Im besten Fall, dass die Basis-Klasse wird eine Menge Arbeit sparen.
InformationsquelleAutor
Juan,
Ich denke gern an Schnittstellen als eine Möglichkeit zur Charakterisierung einer Klasse. Ein besonderer Hund, Rasse, Klasse, sagen, ein YorkshireTerrier, kann eine stammt von der übergeordneten Klasse Hund, aber es ist auch implementiert IFurry, IStubby, und IYippieDog. So definiert die Klasse, welche die Klasse ist aber das interface sagt uns Dinge über Sie.
Der Vorteil dieser ist es mir erlaubt, zum Beispiel, sammeln Sie alle IYippieDog und werfen Sie in meine Ocean-Kollektion. So, jetzt kann ich erreichen, über einen bestimmten Satz von Objekten und finden Sie diejenigen, die die Kriterien erfüllen ich bin auf der Suche-ohne Prüfung der Klasse zu eng.
Finde ich, dass die Schnittstellen wirklich definieren sollte, ein sub-set der öffentlichkeit Verhalten einer Klasse. Wenn er definiert alle öffentlichen Verhalten für alle Klassen, die das implementieren, dann wird es in der Regel nicht vorhanden sein müssen. Sie sagen mir nicht alles, was nützlich ist.
Dieser Gedanke aber geht gegen die Idee, dass jede Klasse sollte über eine Schnittstelle verfügen und Sie sollten den code für das interface. Das ist in Ordnung, aber Sie am Ende mit einer Menge von eins-zu-eins-Schnittstellen, - Klassen und es macht die Sache verwirrend. Ich verstehe, dass die Idee ist, dass es nicht wirklich Kosten nichts zu tun, und jetzt können Sie tauschen Dinge, die in und aus mit Leichtigkeit. Allerdings finde ich, dass ich nur selten zu tun. Die meiste Zeit bin ich nur ändern Sie die vorhandene Klasse im Ort und haben genau die gleichen Probleme, die ich immer habe, wenn die öffentliche Schnittstelle der Klasse geändert werden muss, außer, dass ich jetzt haben, um es zu ändern an zwei stellen.
So, wenn Sie denken wie ich, Sie würde auf jeden Fall sagen, dass Katze und Hund sind IPettable. Es ist eine Charakterisierung, die zu Ihnen passt beides.
Dem anderen Stück dies ist aber sollten Sie den gleichen Basis-Klasse? Die Frage ist, brauchen Sie sich grob behandelt als die gleiche Sache. Gewiß, Sie sind beide Tiere, aber nicht, dass die passen, wie wir Sie zusammen.
Sagen, ich will sammeln alle Tier-Klassen, und legte Sie in meine Lade container.
Oder müssen Sie Säugetiere? Vielleicht brauchen wir eine Art Kreuz Tier Melken Fabrik?
Tun, Sie müssen sogar miteinander verbunden werden? Ist es genug, um zu wissen, dass Sie beide IPettable?
Ich oft das Gefühl, den Wunsch, daraus eine ganze Klassenhierarchie, wenn ich wirklich brauchen nur eine Klasse. Ich tun es in der Erwartung, eines Tages könnte ich es brauchen und in der Regel habe ich nie tun. Auch wenn ich, ich in der Regel finde ich viel zu tun, um es zu beheben. Das ist, weil die erste Klasse, die ich erschaffe, ist nicht der Hund, ich bin nicht so viel Glück, es ist vielmehr das Schnabeltier. Jetzt ist meine ganze Klasse Hierarchie ist auf den bizarren Fall und ich habe eine Menge unnützer code.
Vielleicht finden Sie auch irgendwann, dass nicht alle Katzen sind IPettable (haarlos). Jetzt können Sie verschieben die Schnittstelle für alle abgeleiteten Klassen, die passen. Sie werden feststellen, dass eine viel weniger bedeutende änderung, dass plötzlich Katzen sind nicht mehr abgeleitet aus PettableBase.
InformationsquelleAutor
Hier ist die grundlegende und einfache Definition von interface-und base-Klasse:
cheers
InformationsquelleAutor
Empfehle ich die Verwendung von Zusammensetzung statt von inheritence, Wann immer möglich. Verwenden Sie Schnittstellen, sondern verwenden member-Objekte für base-Umsetzung. So können Sie definieren, dass ein Werk, das Konstrukte, die Ihre Objekte Verhalten sich in einer bestimmten Art und Weise. Wenn Sie möchten das Verhalten ändern, dann machen Sie eine neue Fabrik-Methode (oder die abstrakte Fabrik) , erstellt verschiedene Arten von sub-Objekten.
In einigen Fällen finden Sie möglicherweise, dass Ihre primären Objekte brauchen keine Schnittstellen an alle, wenn alle veränderlichen Verhalten definiert ist, in helper-Objekte.
Also anstelle von IPet-oder PetBase, Sie könnten am Ende mit einem Haustier, welches einen IFurBehavior parameter. Die IFurBehavior parameter wird festgelegt durch die CreateDog () - Methode der PetFactory. Es ist dieser parameter, die aufgerufen wird, für die Schuppen () - Methode.
Wenn Sie dies tun, finden Sie Ihr code ist wesentlich flexibler und die meisten Ihrer einfachen Objekten befassen sich mit sehr grundlegenden system-weiten-Verhalten.
Empfehle ich dieses Muster auch in multiple inheritence Sprachen.
InformationsquelleAutor
Gut erklärt in diesem Java-Welt Artikel
Persönlich Neige ich dazu, Sie zu verwenden-Schnittstellen, Schnittstellen zu definieren - d.h. Teile des system-design, die angeben, wie etwas erreicht werden sollte.
Es ist nicht ungewöhnlich, dass ich eine Klasse implementieren 1 oder mehr Schnittstellen.
Abstrakte Klassen, die ich als Grundlage für etwas anderes.
Das folgende ist ein Auszug aus dem oben erwähnten Artikel JavaWorld.com Artikel, Autor Tony Sintes, 04/20/01
Und darüber hinaus, dass, anstatt zu erweitern, Komponieren die Implementierung, die hinter jeder Methode der Schnittstelle.
InformationsquelleAutor
Beachten Sie auch nicht weggefegt zu werden in OO (siehe blog) und immer Modell-Objekte basierend auf dem Verhalten erforderlich, wenn Sie entwerfen eine app, wo nur das Verhalten, das Sie benötigten, war ein generischer name, und Arten, die für ein Tier ist, dann würden Sie brauchen nur eine Klasse Tier mit einer Eigenschaft für den Namen, anstatt Millionen von Klassen für jedes mögliche Tier in der Welt.
InformationsquelleAutor
Ich habe eine grobe Faustregel
Funktionalität: wahrscheinlich, anders zu sein in allen teilen: - Schnittstelle.
Daten und Funktionalität, die Teile werden größtenteils die gleichen Teile anders: abstrakte Klasse.
Daten und Funktionalität, die tatsächlich arbeiten, wenn die Erweiterung nur mit leichten Veränderungen: gewöhnlichen (konkrete) Klasse
- Daten und-Funktionen, keine Veränderungen geplant: gewöhnlichen (konkrete) Klasse-mit final-modifier.
Daten, und vielleicht-Funktion: nur-lese -: enum-Mitglieder.
Dieser ist sehr rau und bereit und überhaupt nicht streng definiert, sondern es ist ein Spektrum von Schnittstellen, wo alles geändert werden soll, enums, wo alles behoben wird, die ein bisschen wie ein nur-lese-Datei.
InformationsquelleAutor
Schnittstellen sollte klein sein. Wirklich klein ist. Wenn Sie wirklich brechen Sie Ihre Objekte, die anschließend Ihre interfaces wohl nur enthalten, ein paar sehr spezifische Methoden und Eigenschaften.
Abstrakte Klassen sind Verknüpfungen. Gibt es Dinge, die alle Derivate von PetBase teilen, dass Sie kann code einmal und fertig? Wenn ja, dann ist es Zeit für eine abstrakte Klasse.
Abstrakte Klassen sind auch begrenzt. Während Sie geben Ihnen eine tolle Verknüpfung zu produzieren Kind-Objekte jedes Objekt kann nur implementieren Sie eine abstrakte Klasse. Viele Male, ich finde das eine Einschränkung der Abstrakten Klassen, und das ist, warum ich benutze viele Schnittstellen.
Abstrakte Klassen können mehrere Schnittstellen. Ihre PetBase abstrakte Klasse zu implementieren, die IPet (Haustiere müssen Eigentümer) und IDigestion (Haustiere Essen, oder sollten es zumindest). Allerdings PetBase wird wahrscheinlich nicht umsetzen IMammal, da nicht alle Tiere sind Säugetiere, und nicht alle Säugetiere sind Tiere. Sie können auch eine MammalPetBase erweitert PetBase und fügen Sie IMammal. FishBase hätte PetBase und fügen Sie IFish. IFish hätte ISwim und IUnderwaterBreather als Schnittstellen.
Ja, mein Beispiel ist ausführlich über-kompliziert für das einfache Beispiel, aber das ist die große Sache über, wie interfaces und abstrakten Klassen arbeiten zusammen.
InformationsquelleAutor
Fall für die Basis-Klassen über Interfaces erklärt wurde, sowie in der Submain .NET-Coding-Guidelines:
InformationsquelleAutor
Quelle: http://jasonroell.com/2014/12/09/interfaces-vs-abstract-classes-what-should-you-use/
C# ist eine wunderbare Sprache, die gereift ist und sich im Laufe der letzten 14 Jahre. Das ist großartig für uns, die Entwickler, weil eine ausgereifte Sprache bietet uns eine fülle von features für die Sprache, die uns zur Verfügung stehen.
Allerdings mit sehr viel power wird viel Verantwortung. Einige dieser Funktionen können missbraucht werden, oder manchmal ist es schwer zu verstehen, warum würden Sie wählen, verwenden Sie eine Funktion über eine andere. Im Laufe der Jahre, eine Funktion, die ich gesehen habe, viele Entwickler mit zu kämpfen, wenn Sie wählen, um zu verwenden, eine Schnittstelle oder ein zu wählen, verwenden Sie eine abstrakte Klasse. Beide haben Vorteile und Nachteile und den richtigen Zeitpunkt und Ort, zu jeder Verwendung. Aber wie entscheiden wir uns???
Sowohl für die Wiederverwendung gemeinsamer Funktionalitäten zwischen den Arten. Der offensichtlichste Unterschied ist, dass interfaces keine Implementierung für Ihre Funktionalität in der Erwägung, dass abstrakte Klassen erlauben die Implementierung einige "Basis" oder "Standard" - Verhalten und haben dann die Möglichkeit, zu "überschreiben" dieses Standardverhalten mit den Klassen abgeleitete Typen, wenn nötig.
Dies ist alles schön und gut und sorgt für eine tolle Wiederverwendung von code und hält sich an das DRY (Don ' T Repeat Yourself) Prinzip der software-Entwicklung. Abstrakte Klassen sind sehr zu verwenden, wenn Sie haben eine "ist ein" - Beziehung.
Zum Beispiel: Ein golden retriever "ist eine" Art von Hund. So ist ein Pudel. Sie können beide bellen, alle Hunde können. Jedoch, möchten Sie vielleicht zu erklären, dass der Pudel park ist deutlich anders als der "Standard" Hund bellen. Daher könnte es Sinn machen, für Sie, etwas neues zu implementieren, wie folgt:
Wie Sie sehen können, wäre dies eine großartige Möglichkeit, um Ihren code zu TROCKEN und damit für die Implementierung der Basisklasse aufgerufen werden, wenn die Typen, die können nur verlassen sich auf die Standard-Rinde anstelle von einem speziellen Fall die Umsetzung. Die Klassen, wie GoldenRetriever, Boxer, Labor konnte alle Erben konnte der "Standard" (bass class) an zu Bellen, keine Gebühr, nur weil Sie die Umsetzung der Hund abstrakten Klasse.
Aber ich bin sicher, Sie wussten bereits, dass.
Sie sind hier, weil Sie verstehen wollen, warum möchten Sie vielleicht wählen Sie eine Schnittstelle über eine abstrakte Klasse oder Umgekehrt. Auch ein Grund, möchten Sie vielleicht wählen Sie eine Schnittstelle über eine abstrakte Klasse ist, wenn Sie nicht haben oder wollen, um zu verhindern, dass eine default-Implementierung. Dies ist in der Regel, weil die Typen, die das interface nicht in einer "ist ein" - Beziehung. Tatsächlich, Sie müssen nicht verwandt sein, außer der Tatsache, dass jede Art "ist in der Lage" oder die "Fähigkeit" etwas zu tun oder etwas haben.
Nun, was zum Teufel soll das bedeuten? Nun, zum Beispiel: Ein Mensch ist keine Ente...und eine Ente ist nicht ein Mensch. Ziemlich offensichtlich. Jedoch beide eine Ente und eine menschliche habe "die Fähigkeit" zu schwimmen (da der Mensch an seinem Schwimmunterricht in der 1. Klasse 🙂 ). Auch, weil es eine Ente ist nicht ein Mensch, oder Umgekehrt, ist dies nicht eine "ist ein" realationship, sondern eine "kann" - Beziehung und wir können über eine Schnittstelle, die verdeutlichen, dass:
Verwendung von Schnittstellen wie der obige code wird Ihnen erlauben, übergeben Sie ein Objekt in eine Methode, die "in der Lage ist," etwas zu tun. Der code ist nicht egal, wie er es tut...er weiß, dass Sie es nennen können, der Schwimmen-Methode auf das Objekt, und das Objekt wird wissen, welches Verhalten nehmen zur Laufzeit basierend auf dem Typ.
Einmal wieder, dies hilft Ihren code zu TROCKEN bleiben, so dass Sie würde nicht schreiben müssen mehrere Methoden aufrufen, das Objekt Vorform der gleichen Kern-Funktion (ShowHowHumanSwims(human), ShowHowDuckSwims(Ente), etc.)
Verwenden hier eine Schnittstelle ermöglicht den Aufruf von Methoden, um nicht sorgen zu machen über das, was Art ist, welche bzw. wie das Verhalten implementiert ist. Sie weiß einfach, dass Sie die Schnittstelle, die jedes Objekt umgesetzt haben der Baden-Methode, so dass es sicher ist, rufen Sie es in Ihren eigenen code und erlauben, das Verhalten der Baden-Methode behandelt werden, innerhalb der eigenen Klasse.
Zusammenfassung:
Also meine Faustregel ist die Verwendung einer abstrakten Klasse, wenn Sie möchten, implementieren Sie eine "default" - Funktionalität für eine Klassen-Hierarchie oder/und die Klassen oder Typen, mit denen Sie arbeiten, teilen sich eine "ist ein" - Beziehung (ex. Pudel "ist eine" Art von Hund").
Andererseits über eine Schnittstelle, die, wenn Sie nicht eine "ist ein" Beziehung, aber haben die Typen, die gemeinsam "die Fähigkeit", etwas zu tun oder etwas (ex. Ente "ist nicht" ein Mensch. Jedoch, die Ente und den menschlichen Anteil "die Fähigkeit" zu schwimmen).
Anderen Unterschied zu beachten, zwischen abstrakten Klassen und Schnittstellen, die eine Klasse implementieren kann, die man zu vielen Schnittstellen, aber eine Klasse kann nur von Erben von EINER abstrakten Klasse (oder eine andere Klasse für diese Angelegenheit). Ja, Sie können nest Klassen und haben eine Vererbungshierarchie (was bei vielen Programmen zu tun haben sollte), aber Sie kann nicht Erben die beiden Klassen in eine abgeleitete Klassendefinition (diese Regel gilt für C#. In einigen anderen Sprachen, die Sie in der Lage sind, dies zu tun, in der Regel nur, weil der Mangel an Schnittstellen, in diesen Sprachen).
Denken Sie auch daran, wenn interfaces zur Einhaltung des Interface-Segregation-Prinzip (ISP). ISP besagt, dass kein Kunde gezwungen werden sollte, angewiesen auf Methoden, die Sie nicht verwenden. Aus diesem Grund Schnittstellen sollten auf bestimmte Aufgaben konzentrieren und sind in der Regel sehr klein (ex. IDisposable, IComparable ).
Ein weiterer Tipp ist, wenn Sie entwickeln kleine, prägnante bits von Funktionen, Schnittstellen verwenden. Wenn Sie entwerfen große funktionale Einheiten, verwenden Sie eine abstrakte Klasse.
Hoffe, das klärt die Dinge für einige Leute!
Auch wenn man sich denken kann jede bessere Beispiele oder möchten darauf hinweisen, so tun Sie dies bitte in den Kommentaren unten!
InformationsquelleAutor
Ein wichtiger Unterschied ist, dass man nur Erben eine Basis-Klasse, aber Sie implementieren können, viele Schnittstellen. So Sie nur wollen, um eine Basis zu verwenden Klasse, wenn Sie absolut sicher, dass Sie nicht brauchen, um zu Erben auch eine andere Basis-Klasse. Außerdem, wenn Sie finden, Ihre Schnittstelle wird immer groß ist, dann sollten Sie beginnen zu brechen Sie in ein paar logische Abschnitte, die definieren, unabhängige Funktionalität, da es keine Regel, dass Ihre Klasse nicht umsetzen können Sie alle (oder die, die Sie definieren können einer anderen Schnittstelle, die einfach ist, erbt Sie alle, um Sie zu gruppieren).
InformationsquelleAutor
Als ich anfing, das lernen über Objekt-orientierte Programmierung, habe ich die einfach und wahrscheinlich häufigste Fehler, der mit der Vererbung zu gemeinsamen Verhalten - auch dort, wo das Verhalten nicht wesentlich auf die Natur des Objekts.
Weiter zu bauen auf ein Beispiel, das viel verwendet in dieser speziellen Frage, gibt es viele Dinge, die petable - freundinnen, Autos, fuzzy decken... - also ich hätte einen Petable Klasse zur Verfügung gestellt, dass dieses gemeinsame Verhalten, und die verschiedenen Klassen Erben.
Jedoch petable ist nicht Teil der Natur, diese Objekte. Es gibt weitaus mehr wichtige Konzepte, die sind wichtig, um deren Natur - die Freundin ist eine person, das Auto ist ein Geländewagen, die Katze ist ein säugetier...
Verhaltensweisen zugeordnet werden soll, werden zuerst die Schnittstellen (einschließlich der Standard-Schnittstelle der Klasse), und gefördert werden, um eine Basis-Klasse nur, wenn Sie (a) gemeinsam eine große Gruppe von Klassen, sind Untergruppen einer größeren Klasse - im gleichen Sinne, dass "Katze" und "person" sind Untergruppen von "säugetier".
Der Haken ist, nachdem Sie verstehen, Objekt-orientierte design ausreichend besser, als ich es Tat auf den ersten, werden Sie in der Regel tun dies automatisch, ohne darüber nachzudenken. Also die Nackte Wahrheit der Aussage "code, um eine Schnittstelle, nicht eine abstrakte Klasse" wird so offensichtlich, Sie haben eine harte Zeit zu glauben, jemand würde sich die Mühe zu sagen, es - und starten Sie versuchen zu Lesen, andere Bedeutungen hinein.
Andere Sache, die ich hinzufügen, dass, wenn eine Klasse rein Abstrakt - ohne nicht-abstrakte, nicht-geerbten member oder Methoden ausgesetzt, Kind, Elternteil oder client - warum dann ist es eine Klasse? Es könnte ersetzt werden, in einigen Fällen durch eine Schnittstelle und in anderen Fällen durch Null.
InformationsquelleAutor
Lieber über Schnittstellen abstrakte Klassen
Begründung,
die wichtigsten Punkte zu berücksichtigen [zwei bereits hier erwähnt] sind :
- Schnittstellen. Da Java keine Mehrfachvererbung, mit
abstrakte Klassen verhindert, dass die Benutzer mit jeder anderen Klasse
Hierarchie. Im Allgemeinen bevorzugen Schnittstellen, wenn es gibt keine Standardeinstellung,
Implementierungen oder Staat. Java-collections bieten gute Beispiele
diese (Anzeigen, Satz, etc.).
die Kompatibilität. Wenn Kunden über eine Schnittstelle, Sie können es nicht ändern;
wenn Sie verwenden eine abstrakte Klasse ist, können Sie noch hinzufügen, Verhalten ohne
brechen vorhandenen code. Wenn unter "Kompatibilität" ein Anliegen ist, erwägen Sie die Verwendung
abstrakte Klassen.
prüfen, bietet ein interface und eine abstrakte Implementierung von it -.
Diese helfen den Kunden, aber immer noch erlauben, Ihnen eine größere Freiheit, wenn
gewünschte [1].
Natürlich, das Thema wurde ausführlich diskutiert
anderswo [2,3].
[1] Sie fügt hinzu, mehr code, natürlich, aber wenn die Kürze ist Ihre primäre Sorge, Sie sollten wahrscheinlich vermieden haben Java in den ersten Platz!
[2] Joshua Bloch, Effective Java, Artikel 16-18.
[3] http://www.codeproject.com/KB/ar...
InformationsquelleAutor
Vorherigen Kommentare über die Verwendung von abstrakten Klassen, die für die gemeinsame Umsetzung ist definitiv auf dem mark. Ein Vorteil, den ich habe nicht gesehen, noch erwähnt wird, dass die Verwendung von interfaces macht es viel einfacher zu implementieren mock-Objekte für den Zweck von unit-Tests. Definition von IPet-und PetBase als Jason Cohen beschrieben, können Sie zu verspotten verschiedene Daten Bedingungen einfach, ohne den Aufwand einer physischen Datenbank (bis Sie sich entscheiden, es ist Zeit, zu testen, die Reale Sache).
InformationsquelleAutor
Nicht verwenden eine Basis-Klasse, es sei denn, Sie wissen, was es bedeutet, und dass es gilt in diesem Fall. Wenn es zutrifft, verwenden Sie es, andernfalls die Verwendung von Schnittstellen. Aber beachten Sie die Antwort über kleine Schnittstellen.
Öffentlicher Vererbung ist überstrapaziert in OOD und drückt viel mehr als die meisten Entwickler realisieren oder bereit sind, zu Leben bis zu. Finden Sie die Liskov Substitutablity Prinzip
Kurz gesagt, wenn A "a" B, dann A verlangt nicht mehr als B und erzielt nicht weniger als B ist, für jede Methode, die es macht.
InformationsquelleAutor
Konzeptionell eine Schnittstelle wird verwendet, um formal und semi-formal definiert eine Reihe von Methoden, die ein Objekt zu bieten. Formal bedeutet, dass eine Reihe von Methodennamen und Signaturen, semi-formal bedeutet menschlich lesbare Dokumentation mit den damit verbundenen Methoden. Schnittstellen sind nur Beschreibungen eines API (API steht für Application Programmer ' Schnittstelle), können Sie nicht enthalten keine Implementierung, und es ist nicht möglich, Sie zu verwenden, oder führen Sie eine Schnittstelle. Sie machen nur explizite, den Vertrag, wie Sie sollen interagieren mit einem Objekt.
Klassen eine Implementierung bereitstellen, können Sie erklären, dass Sie die Umsetzung der null, eine oder mehrere Schnittstellen. Wenn eine Klasse geerbt werden, die Konvention ist als Präfix den Namen der Klasse mit "Base".
Gibt es einen Unterschied zwischen einer Basisklasse und einer Abstrakten Basis-Klassen (ABC). ABCs mix Schnittstelle und Implementierung zusammen. Abstrakt außerhalb der computer-Programmierung bedeutet "Zusammenfassung", das ist "Abstract == Interface". Eine Abstrakte Basisklasse kann dann beschreiben, der sowohl eine Schnittstelle als auch eine leere, eine teilweise oder komplette Realisierung, die geerbt werden.
Meinungen zum Gebrauch von Interfaces versus Abstrakte Basisklassen versus nur Klassen wird sehr stark variieren basierend auf, was Sie entwickeln, und welche Sprache Sie entwickeln sich. Schnittstellen sind oft nur für statisch typisierte Sprachen wie Java oder C#, aber dynamisch typisierte Sprachen können auch Interfaces und Abstrakte Basisklassen. In Python zum Beispiel, die Unterscheidung wird klar zwischen einer Klasse, die erklärt, dass es implementiert eine Schnittstelle, und ein Objekt, das eine Instanz einer Klasse, und es wird gesagt, bieten Schnittstelle. Es ist möglich, eine dynamische Sprache, dass zwei Objekte, die beide Instanzen von der gleichen Klasse, erklären können, dass Sie völlig verschiedenen Schnittstellen. In Python ist dies nur möglich für Objekt-Attribute, während Methoden werden geteilt zwischen Staat alle Objekte einer Klasse. Allerdings in Ruby Objekte können pro Instanz-Methoden, so ist es möglich, dass die Schnittstelle zwischen zwei Objekten der gleichen Klasse variieren kann, so viel wie der Programmierer wünscht (aber Ruby hat keine explizite Art und Weise der Deklaration von Schnittstellen).
In dynamischen Sprachen die Schnittstelle zu einem Objekt, wird oft implizit angenommen, entweder durch introspecting ein Objekt und Fragen Sie, welche Methoden es bietet (Aussehen, Bevor Sie springen), oder vorzugsweise, indem Sie einfach versucht, die gewünschte Schnittstelle auf ein Objekt und Ausnahmen abfangen, wenn sich das Objekt nicht vorsehen, dass die Schnittstelle (Einfacher, um Vergebung zu Bitten, als die Berechtigung). Dies führt zu "false positives", wo zwei Interfaces dieselbe Methode Namen, aber semantisch unterschiedlich, aber der trade-off ist, dass dein code ist flexibler, da Sie nicht brauchen, um über Sie bis vor antizipieren alle möglichen Verwendungen des Codes.
InformationsquelleAutor
Andere option im Auge zu behalten ist die Verwendung der "hat-ein" - Beziehung, auch bekannt als "implementiert" oder "Komposition." Manchmal ist das ein sauberer, flexibler Weise zur Struktur der Dinge als die Verwendung von "is-a" Vererbung.
Kann es nicht machen so viel Sinn, logisch zu sagen, dass Hund und Katze beide "haben" ein Haustier, aber es vermeidet common multiple Vererbung Fallstricke:
Ja, dieses Beispiel zeigt, dass es eine Menge von code-Duplizierung und Mangel an Eleganz zu tun, die Dinge auf diese Weise. Aber man sollte auch zu schätzen wissen, dass dies hilft, um Hund und Katze entkoppelt von der Pet-Klasse (in, Hund und Katze haben keinen Zugriff auf die privaten Mitglieder von Pet -), und es lässt Raum für Hund und Katze, die Erben, etwas anderes-vielleicht die Mammal-Klasse.
Komposition ist vorzuziehen, wenn keine privaten Zugang erforderlich ist, und Sie brauchen nicht zu finden, um Hund und Katze mit Hilfe von generischen Pet Referenzen/Zeigern. Interfaces, die generische Referenz-Fähigkeit und kann Ihnen helfen, reduzieren auf die Ausführlichkeit des Codes, aber Sie können auch vernebeln Dinge, wenn Sie sind schlecht organisiert. Vererbung ist nützlich, wenn Sie brauchen, privaten member zugreifen und Sie verwenden, die Sie Begehen Sie sich selbst zu hoch Kupplung Ihren Hund und Katze-Klassen, um Ihre Pet-Klasse, die eine steile Kosten zu bezahlen.
Zwischen Vererbung, Komposition und Schnittstellen es gibt keine Weise, die immer Recht hat, und es hilft, zu überlegen, wie alle drei Optionen können verwendet werden, in Harmonie. Von den drei, die Vererbung ist in der Regel die option, die verwendet werden sollte, die am wenigsten oft.
InformationsquelleAutor
Es hängt von Ihren Anforderungen ab. Wenn IPet ist einfach genug, ich würde es vorziehen, zu implementieren. Ansonsten, wenn PetBase implementiert, die eine Tonne von Funktionen, die Sie nicht duplizieren möchten, dann haben Sie an ihm.
Den Nachteil der Implementierung einer Basis-Klasse ist die Voraussetzung, um
override
(odernew
) vorhandenen Methoden. Dies macht Sie zu virtuellen Methoden, die bedeutet, dass Sie vorsichtig sein müssen, wie Sie das object-Instanz.Schließlich der einzige Erbe .NET tötet mich. Ein naives Beispiel: Sagen wir, du machst ein Benutzer die Kontrolle, so Erben Sie
UserControl
. Aber jetzt sind Sie gesperrt, auch ErbenPetBase
. Dies zwingt Sie, sich neu zu organisieren, zu machen, wie einPetBase
Klasse, statt.InformationsquelleAutor
@Joel: Einige Sprachen (z.B. C++) erlauben, multiple Vererbung.
Der Kurs C++ hat ein Konzept der Schnittstellen....ohne virtuelle Funktionen, auch.
InformationsquelleAutor
Ich in der Regel nicht umsetzen, bis ich eines brauchen. Ich bevorzuge Schnittstellen über abstrakte Klassen, denn das gibt ein wenig mehr Flexibilität. Wenn es gemeinsame Verhalten in einigen der Erben-Klassen, die ich verschieben, dass oben und stellen Sie eine abstrakte Basisklasse. Ich sehe nicht die Notwendigkeit für beide, da Sie im wesentlichen server den gleichen Zweck, und sowohl ein bad code smell (imho), dass die Lösung wurde mit over-engineered.
InformationsquelleAutor
Bezüglich C#, in einigen Sinnen interfaces und abstrakten Klassen können austauschbar sein. Die Unterschiede sind jedoch: i) die Schnittstellen nicht implementieren kann code; ii), da diese Schnittstellen nicht aufrufen kann, weiter oben auf dem stack als Unterklasse; und iii) kann nur von abstrakten Klassen geerbt werden kann, die auf einer Klasse, in der Erwägung, dass mehrere Schnittstellen implementiert werden kann, auf eine Klasse.
InformationsquelleAutor
Def, Schnittstelle stellt eine Schicht für die Kommunikation mit anderen code. Alle öffentlichen Eigenschaften und Methoden einer Klasse sind standardmäßig Umsetzung der impliziten Schnittstelle. Wir können auch definieren ein interface als eine Rolle, wenn überhaupt irgendeine Klasse muss diese Rolle spielen, er hat es zu implementieren, gibt es verschiedene Formen der Umsetzung, je nach der Klasse, es umzusetzen. Daher, wenn Sie darüber reden-interface, über das Sie sprechen über Polymorphismus und wenn Sie sprechen über die base-Klasse, Sie sprechen von Vererbung. Zwei Konzepte von Hoppla !!!
InformationsquelleAutor
Ich habe festgestellt, dass ein Muster von Interface - > Abstract > Betonarbeiten in der folgenden use-case:
Die abstrakte Klasse definiert die Standard-shared-Attribute der konkreten Klassen, dennoch erzwingt das interface. Zum Beispiel:
Nun, da alle Säugetiere haben Haare und Brustwarzen (AFAIK, ich bin kein Zoologe), können wir die Rolle dieser in der abstrakten Basisklasse
Dann die konkreten Klassen definieren lediglich, dass Sie aufrecht gehen.
Dieses design ist schön, wenn es viele konkrete Klassen, und Sie wollen nicht zu halten boilerplate einfach zu Programmieren einer Schnittstelle. Wenn neue Methoden wurden Hinzugefügt, um die Schnittstelle, es würde brechen alle der resultierenden Klassen, so sind Sie noch immer die Vorteile der interface-Ansatz.
In diesem Fall ist die Zusammenfassung könnte genauso gut aus Beton; jedoch die abstrakte Bezeichnung hilft zu betonen, dass dieses Muster eingesetzt wird.
InformationsquelleAutor
Einen Erben von einer Basisklasse sollte eine "ist ein" - Beziehung. Interface stellt Eine "implements" - Beziehung.
So verwenden Sie nur eine Basisklasse, wenn Ihre Erben behalten das ist eine Beziehung.
InformationsquelleAutor