Ich entwerfe mein eigenes kleines OOP-Programm zur Simulation von Vampiren, Wölfen, Menschen und Lastwagen und versuche, mein eigenes begrenztes Verständnis von Schnittstellen zu implementieren.
( Ich abstrahiere hier noch und habe noch keine Code-Implementierung, es ist also eher eine Frage des OOP-Designs ... denke ich!)
Habe ich Recht , wenn ich nach einem „gemeinsamen Verhalten“ zwischen diesen Klassen suche und sie als Schnittstellen implementiere ?
Zum Beispiel, Vampire und Wölfe beißen ... sollte ich also ein Biss-Interface haben?
public class Vampire : Villain, IBite, IMove, IAttack
Ebenso für Trucks ...
public class Truck : Vehicle, IMove
Und für Menschen ...
public class Man : Human, IMove, IDead
Ist mein Denken hier richtig? (Schätze deine Hilfe)
object-oriented
interfaces
user3396486
quelle
quelle
IEnumerable
,IEquatable
etc.Antworten:
Im Allgemeinen möchten Sie Schnittstellen für gemeinsame Merkmale Ihrer Klasse haben.
Ich stimme in den Kommentaren halb mit @Robert Harvey überein, der sagte, dass Schnittstellen normalerweise abstraktere Merkmale von Klassen darstellen. Trotzdem empfinde ich es als eine gute Möglichkeit, ausgehend von konkreten Beispielen abstrakt zu denken.
Während Ihr Beispiel technisch korrekt ist (dh ja, sowohl Vampire als auch Wölfe beißen, so dass Sie eine Schnittstelle dafür haben können), ist es eine Frage von Relevanz. Jedes Objekt hat Tausende von Eigenschaften (z. B. können Tiere Fell haben, schwimmen, Bäume besteigen usw.). Wirst du ein Interface für alle machen? Sehr unwahrscheinlich.
Normalerweise möchten Sie, dass Schnittstellen für sinnvolle Dinge in einer Anwendung als Ganzes zusammengefasst werden. Wenn Sie beispielsweise ein Spiel erstellen, können Sie über eine Reihe von IMove-Objekten verfügen und deren Position aktualisieren. Wenn Sie das nicht möchten, ist die IMove-Oberfläche ziemlich nutzlos.
Der Punkt ist, nicht zu viel Ingenieur. Sie müssen überlegen, wie Sie diese Schnittstelle verwenden möchten, und 2 Klassen mit einer gemeinsamen Methode sind kein ausreichender Grund, eine Schnittstelle zu erstellen.
quelle
IBite
ist es nicht besonders nützlich, aber Sie möchten vielleicht, dassIAttack
Sie über alle DingeIUpdate
IPhysicsEnabled
Sieht so aus, als würden Sie eine Reihe von Schnittstellen für einzelne Methoden erstellen . Dies ist auf den ersten Blick in Ordnung, aber denken Sie daran, dass die Schnittstellen nicht den Klassen gehören, die sie implementieren. Sie gehören den Kunden, die sie verwenden. Die Kunden entscheiden, ob etwas etwas sein muss, das sich bewegen und angreifen kann.
Wenn ich eine
Combat
Klasse mit einerfight()
Methode habe, muss diese Methode wahrscheinlich sowohlmove()
als auchattack()
für dasselbe Objekt aufgerufen werden. Dies deutet stark auf die Notwendigkeit einerICombatant
Schnittstelle hin,fight()
die auf-move()
undattack()
durchgehen kann. Dies ist sauberer alsfight()
einIAttack
Objekt zu nehmen und es zu werfen, umIMove
zu sehen, ob es sich auch bewegen kann.Das bedeutet nicht, dass Sie keine
IMove
IAttack
Schnittstellen haben können. Ich hoffe nur, dass Sie sie nicht machen, ohne dass ein Kunde sie braucht. Umgekehrt, wenn kein Client jemals ein Objekt bewegen und angreifen muss,ICombatant
ist dies nicht erforderlich.Diese einfache Sichtweise auf Schnittstellen geht oft verloren, weil die Leute gerne Beispiele befolgen. Die ersten Schnittstellen, denen wir ausgesetzt sind, befinden sich in Bibliotheken. Leider haben Bibliotheken keine Ahnung, was ihre Kunden sind. Sie können also nur die Bedürfnisse ihrer Kunden erraten. Nicht das beste Beispiel zu folgen.
quelle
Überlegen Sie, ob es üblich sein wird, Sammlungen von Objekten mit unterschiedlichen Kombinationen von Fähigkeiten zu haben, und ob Code möglicherweise eine Aktion für die Elemente innerhalb einer Sammlung ausführen möchte, die diese unterstützen . Wenn ja, und wenn es ein vernünftiges "Standardverhalten" für Objekte gibt, die für bestimmte Aktionen keine nützliche Unterstützung bieten, kann es hilfreich sein, Schnittstellen von einer Vielzahl von Klassen implementieren zu lassen, nicht nur von solchen, die sich nützlich verhalten können.
Nehmen wir zum Beispiel an, nur wenige Arten von Kreaturen können Woozles haben, und man möchte, dass solche Kreaturen eine
NumerOfWoozles
Eigenschaft haben. Wenn eine solche Eigenschaft in einer Schnittstelle vorhanden wäre, die nur von Kreaturen implementiert wurde, die Woozles haben können, müsste der Code, der die Gesamtzahl der Woozles ermitteln möchte, die von einer Sammlung von Kreaturen gemischter Typen gehalten werden, etwa Folgendes sagen:Wenn jedoch WoozleCount ein Mitglied von Creature / ICreature wäre, könnte der Code wie folgt vereinfacht werden:
Während einige Leute auf der Idee scheuern könnten eine WoozleCount Eigenschaft jede Kreatur implementieren zu haben , die wirklich für einige Subtypen nur dann sinnvoll ist, würde die Eigenschaft sein sinnvoll für alle, auch nicht , dass es mit Gegenständen nützlich sein , bekannt diesen Typs zu sein, und ich würde die "Küchenspüle" -Schnittstelle als weniger nach Code riechend betrachten als den Trycast-Operator.
quelle