Beispielsweise:
Sagen wir , ich Klassen A
, B
, C
. Ich habe zwei Schnittstellen, nennen wir sie IAnimal
und IDog
. IDog
erbt von IAnimal
. A
und B
sind IDog
s, während C
es nicht ist, aber es ist ein IAnimal
.
Der wichtige Teil ist, dass es IDog
keine zusätzlichen Funktionen gibt. Es wird nur verwendet, um bestimmte Methoden als Argument zuzulassen A
und B
nicht C
zu übergeben.
Ist das eine schlechte Praxis?
object-oriented
interfaces
Kendall Frey
quelle
quelle
IAnimal
undIDog
sind schreckliche Tautologienamen!MyProject.Data.IAnimal
undMyProject.Data.Animal
sind besser alsMyProject.Data.Interfaces.Animal
undMyProject.Data.Implementations.Animal
Interface
oderImplementation
, ob in einem repetitiven Präfix oder einem Namespace, um eine Tautologie handelt und gegen DRY verstößt.Dog
ist alles, was Sie interessieren sollte.PitBull extends Dog
benötigt auch keine Implementierungsredundanz, das Wortextends
sagt mir alles, was ich wissen muss, lies den Link, den ich in meinem ursprünglichen Kommentar gepostet habe.Antworten:
Schnittstelle, die kein Mitglied hat oder genau dieselben Mitglieder hat, mit einer anderen Schnittstelle, die von derselben Schnittstelle namens Marker Interface geerbt wird und die Sie als Marker verwenden.
Es ist keine schlechte Praxis, aber die Benutzeroberfläche kann durch Attribute (Anmerkungen) ersetzt werden, wenn die von Ihnen verwendete Sprache dies unterstützt.
Ich kann zuversichtlich sagen, dass es keine schlechte Praxis ist, da ich in Orchard Project ein stark genutztes "Marker Interface" -Muster gesehen habe
Hier ist ein Beispiel aus dem Orchard-Projekt.
Bitte beziehen Sie sich auf Marker Interface .
quelle
C
an eine Methode übergeben können, die ein erwartetIDog
.Kennel
Klasse, die eine Liste vonIDog
s speichert .Ja, es ist eine schlechte Praxis in fast jeder Sprache.
Typen sind nicht dazu da, Daten zu kodieren. Sie sind ein Hilfsmittel, um zu beweisen, dass Ihre Daten dahin gelangen, wo sie benötigt werden, und sich so verhalten, wie sie sich verhalten müssen. Der einzige Grund für die Untertypisierung besteht darin, dass sich ein polymorphes Verhalten ändert (und nicht immer dann).
Da nicht getippt wird, wird vorausgesetzt, was ein IDog kann. Ein Programmierer denkt eine Sache, ein anderer denkt eine andere und die Dinge brechen zusammen. Oder die Dinge, die es darstellt, nehmen zu, wenn Sie eine feinkörnigere Steuerung benötigen.
[Bearbeiten: Klarstellung]
Ich meine, Sie machen eine Logik, die auf der Schnittstelle basiert. Warum funktionieren manche Methoden nur bei Hunden und andere bei Tieren? Diese Differenz ist ein impliziter Vertrag, da es kein tatsächliches Mitglied gibt, das die Differenz liefert. Keine aktuellen Daten im System. Der einzige Unterschied ist die Benutzeroberfläche (daher der Kommentar ohne Eingabe) und was dies bedeutet, wird sich zwischen den Programmierern unterscheiden. [/bearbeiten]
Bestimmte Sprachen bieten Charakterzugsmechanismen, bei denen dies nicht so schlimm ist, aber bei denen der Schwerpunkt eher auf Fähigkeiten als auf Verfeinerungen liegt. Ich habe wenig Erfahrung mit ihnen und kann daher nicht mit den dortigen Best Practices sprechen. In C ++ / Java / C # allerdings ... nicht gut.
quelle
Kennel
Klasse habe, in der eine Liste vonIDog
s gespeichert ist.Ich kenne C # nur gut, daher kann ich das für die OO-Programmierung im Allgemeinen nicht sagen, aber als C # -Beispiel, wenn Sie Klassen kategorisieren müssen, sind die offensichtlichen Optionen Schnittstellen, Enum-Eigenschaften oder benutzerdefinierte Attribute. Normalerweise würde ich die Schnittstelle wählen, egal was andere denken.
quelle
Es ist nichts Falsches daran, eine Schnittstelle zu haben, die eine andere Schnittstelle erbt, ohne neue Mitglieder hinzuzufügen, wenn erwartet wird, dass alle Implementierungen der letzteren Schnittstelle in der Lage sind, nützliche Dinge zu tun, die einige Implementierungen der ersteren möglicherweise nicht können. In der Tat ist es ein gutes Muster, das IMHO eher in Dingen wie dem .net Framework hätte verwenden sollen, zumal ein Implementierer, dessen Klasse natürlich die von der stärker abgeleiteten Schnittstelle implizierten Einschränkungen erfüllen würde, dies einfach durch Implementieren der stärker abgeleiteten Schnittstelle anzeigen kann , ohne den Implementierungscode oder die Deklarationen der Mitglieder ändern zu müssen.
Angenommen, ich habe die folgenden Schnittstellen:
Es wird
IImmutableFoo.AsImmutable()
erwartet, dass eine Implementierung von sich selbst zurückgibt. Von einer Implementierung einer veränderlichen Klasse wirdIMaybeMutableFoo.AsImmutable()
erwartet, dass sie ein neues, tief unveränderliches Objekt zurückgibt, das eine Momentaufnahme der Daten enthält. Eine Routine, die einen Schnappschuss der in einer gespeicherten Daten speichern möchte, kann zuIMaybeMutableFoo
Überlastungen führen:In Fällen, in denen der Compiler nicht weiß, dass es sich bei dem zu speichernden Objekt um einen handelt
IImmutableFoo
, ruft er aufAsImmutable()
. Die Funktion sollte schnell zurückkehren, wenn das Element bereits unveränderlich ist, ein Funktionsaufruf über eine Schnittstelle jedoch noch einige Zeit in Anspruch nimmt. Wenn der Compiler weiß, dass das Element bereits ein Element istIImmutableFoo
, kann er den unnötigen Funktionsaufruf überspringen.quelle