AFAIK bietet drei gängige Methoden, um die Wiederverwendbarkeit von OOP zu implementieren
- Vererbung: Normalerweise ist es eine Beziehung (eine Ente ist ein Vogel).
- Zusammensetzung: in der Regel zur Darstellung hat eine Beziehung (ein Auto hat einen Motor)
- Eigenschaften (zB das Schlüsselwort trait in PHP): ... da bin ich mir nicht sicher
Obwohl es für mich so aussieht, als könnten Merkmale sowohl Has-A- als auch Is-A-Beziehungen implementieren, bin ich mir nicht sicher, für welche Art von Modellierung es gedacht war. Für welche Situationen wurden Merkmale entwickelt?
object-oriented-design
Extrakun
quelle
quelle
Antworten:
Eigenschaften sind ein weiterer Weg, um Komposition zu machen. Stellen Sie sich diese als eine Möglichkeit vor, alle Teile einer Klasse zur Kompilierungszeit (oder JIT-Kompilierungszeit) zusammenzustellen und die konkreten Implementierungen der Teile zusammenzustellen, die Sie benötigen.
Grundsätzlich möchten Sie Merkmale verwenden, wenn Sie Klassen mit unterschiedlichen Merkmalskombinationen erstellen. Diese Situation tritt am häufigsten bei Personen auf, die flexible Bibliotheken schreiben, die andere nutzen können. Hier ist zum Beispiel die Deklaration einer Unit-Test-Klasse, die ich kürzlich mit ScalaTest geschrieben habe :
Unit-Test-Frameworks bieten eine Vielzahl unterschiedlicher Konfigurationsoptionen, und jedes Team hat unterschiedliche Vorlieben, wie es Dinge tun möchte. Durch Einfügen der Optionen in Merkmale (die
with
in Scala gemischt verwendet werden ) kann ScalaTest all diese Optionen anbieten, ohne Klassennamen wieWordSpecLikeWithMatchersAndFutures
oder eine Menge boolescher Laufzeitflags wie erstellen zu müssenWordSpecLike(enableFutures, enableMatchers, ...)
. Dies macht es einfach, dem Open / Closed-Prinzip zu folgen . Sie können neue Funktionen und neue Kombinationen von Funktionen hinzufügen, indem Sie einfach ein neues Merkmal hinzufügen. Dies erleichtert auch das Befolgen des Interface-Segregation-Prinzips , da Sie Funktionen, die nicht allgemein benötigt werden, einfach in ein Merkmal einfügen können.Merkmale sind auch eine gute Möglichkeit, gemeinsamen Code in mehrere Klassen einzuteilen, die für die gemeinsame Nutzung einer Vererbungshierarchie nicht sinnvoll sind. Vererbung ist eine sehr eng gekoppelte Beziehung, und Sie sollten diese Kosten nicht bezahlen, wenn Sie helfen können. Merkmale sind eine viel lockerer gekoppelte Beziehung. In meinem obigen Beispiel habe ich
MyCustomTrait
eine Scheindatenbankimplementierung problemlos für mehrere ansonsten nicht verwandte Testklassen freigegeben.Die Abhängigkeitsinjektion erreicht viele der gleichen Ziele, jedoch zur Laufzeit basierend auf Benutzereingaben anstatt zur Kompilierungszeit basierend auf Programmierereingaben. Merkmale sind auch eher für Abhängigkeiten gedacht, die semantisch Teil derselben Klasse sind. Sie setzen die Teile einer Klasse zusammen, anstatt andere Klassen mit anderen Verantwortlichkeiten anzurufen.
Frameworks für die Abhängigkeitsinjektion erreichen viele der gleichen Ziele zur Kompilierungszeit basierend auf den Eingaben des Programmierers, sind jedoch weitgehend eine Problemumgehung für Programmiersprachen ohne angemessene Unterstützung von Merkmalen. Merkmale bringen diese Abhängigkeiten in den Bereich der Typprüfung des Compilers, mit einer saubereren Syntax und einem einfacheren Erstellungsprozess, der eine klarere Unterscheidung zwischen Abhängigkeiten zur Kompilierungszeit und zur Laufzeit ermöglicht.
quelle
with
Operator unterscheidet sie undwith
ist eine Kompositionsoperation. Und ja, Merkmale ersetzen DI, ohne dass sie am Einstiegspunkt des Codes definiert werden müssen. Das ist eines der Dinge, die sie meiner Meinung nach vorzuziehen machen.