
Ich arbeite in einer Spieleentwicklungsfirma, aber als Heimhobby habe ich mich in letzter Zeit für die Entwicklung mobiler Anwendungen interessiert. Als mich ein Freund zu einem Treffen einlud, das der Entwicklung mobiler Anwendungen mit dem Flutter-Framework gewidmet war, stimmte ich daher mit Vergnügen zu. Nachdem ich Flutter dort in Aktion ausprobiert hatte, beschloss ich, diese Technologie definitiv zu studieren. Da mir der für die Entwicklung benötigte Dart unbekannt war, wurde auch das Sprachenlernen in das Pflichtprogramm aufgenommen. Nachdem ich ein wenig über die Codebeispiele gesessen hatte, fand ich, dass Dart eine leicht verständliche und prägnante Sprache ist, die mir sehr gut gefallen hat. Eines der Merkmale von Dart, das mir gefallen hat, sind die Verunreinigungen.
Was sind Verunreinigungen?
Für eine erste Bekanntschaft werde ich einen
Auszug aus Wikipedia geben .
Beimischung (English Mix In) ist ein Element einer Programmiersprache (normalerweise eine Klasse oder ein Modul), das ein klar definiertes Verhalten implementiert. Wird verwendet, um das Verhalten anderer Klassen zu verdeutlichen, nicht um unabhängig verwendete Objekte zu generieren.
In Dart werden solche Konstrukte durch das Wort
mixin vor dem Namen definiert.
Die obige Definition bedeutet, dass wir die Funktionalität von logisch isolierten Verhaltensweisen erhalten, die anderen Klassen hinzugefügt werden können.
Erinnert es Sie an die Möglichkeit einer Mehrfachvererbung? Ja, aber es scheint mir, dass der Ansatz der Verunreinigung besser ist. Und warum, schauen wir uns ein Beispiel an.
Angenommen, wir haben eine abstrakte Klasse Tier.
abstract class Animal { void voice(); }
Und auch die Katzen- und Hundeklassen, die die Tierklasse implementieren.
class Cat extends Animal { void voice() { print(“Meow”); } } class Dog extends Animal { void voice() { print(“Woof”); } }
Und dann brauchten wir plötzlich ... Ja, ja, ich persönlich habe solche Dinge während der Entwicklung nicht.
Und im Falle einer Mehrfachvererbung würden wir dasselbe tun.
class CatDog extends Cat, Dog { }
Sobald wir jedoch unserem Haustier unseren Sprachbefehl aussprechen, kommt es zu einer sehr unangenehmen Situation - es ist nicht klar, was genau er antworten soll, da die
Sprachmethode in beiden Klassen implementiert ist. Diese Situation ist allgemein bekannt und wird als
Diamantproblem oder
tödlicher Diamant des Todes bezeichnet .
Bei Verkäufen durch Verunreinigungen werden wir nicht darauf stoßen.
lass Animal { void voice() { print(“Hakuna Matata!”); } } mixin Cat { void voice() { print(“Meow”); } } mixin Dog { void voice() { print(“Woof”); } } class CatDog extends Animal with Cat, Dog { }
Und was werden wir hören, wenn wir jetzt einen Sprachbefehl geben? In diesem Fall - Woof, und wie Sie bereits verstanden haben, hängt es von der Reihenfolge der Zugabe von Verunreinigungen ab. Dies geschieht, weil ihre Addition nicht parallel, sondern sequentiell erfolgt.
Ich habe die Animal-Klasse speziell implementiert, um eine in
Dart 2.1 eingeführte Funktion zu markieren. Zuvor konnten Verunreinigungen nur Klassen hinzugefügt werden, die von
Object erben. Ab Version 2.1 wird das Hinzufügen von Klassen zu den Erben implementiert.
Dieser Mechanismus macht es sehr bequem, die gemeinsamen Teile der Funktion zu erstellen und zu verwenden, wodurch das Problem der Codeduplizierung gelöst wird. Schauen wir uns ein Beispiel an.
abstract class Sportsman { void readySteadyGo(); } mixin SkiRunner { void run() { print(“Ski, ski, ski”); } } mixin RifleShooter { void shot() { print(“Pew, pew, pew”); } } class Shooter() extends Sportsman with RifleShooter { void readySteadyGo() { shot(); } } class Skier() extends Sportsman with SkiRunner { void readySteadyGo() { run(); } } class Biathlete() extends Sportsman with SkiRunner, RifleShooter { void readySteadyGo() { run(); shot(); } }
Wie Sie sehen können, haben wir den gesamten doppelten Code nach Verunreinigungen verteilt und in jeder der Implementierungen nur die erforderlichen verwendet.
Während der Entwicklung kann es vorkommen, dass die Funktionalität einer der Verunreinigungen nicht für alle Klassen öffentlich zugänglich sein sollte. Ein Mechanismus, mit dem wir diese Einschränkungen auferlegen können, ist ebenfalls verfügbar. Dies ist das Schlüsselwort on in der Beimischungsdeklaration zusammen mit dem Klassennamen. Daher beschränken wir die Verwendung von Verunreinigungen nur auf Klassen, die das angegebene oder von ihm geerbte implementieren.
Zum Beispiel:
class A { } abstract class B { } mixin M1 on A { } mixin M2 on B { }
Dann können wir ähnliche Klassen deklarieren:
class C extends A with M1 { } class D implements B with M2 { }
Beim Versuch, so etwas zu deklarieren, wird jedoch ein Fehler angezeigt:
class E with M1, M2 { }
Verwendung in der Flatteranwendung
Wie oben erwähnt, können Sie mit Verunreinigungen die Vervielfältigung von Code beseitigen und separate logische Teile erstellen, die wiederverwendet werden können. Aber wie ist dies allgemein auf Flutter anwendbar, wo alles atomar ist und so in Widgets unterteilt ist, die für eine bestimmte Funktionalität verantwortlich sind? Als Beispiel stellte ich mir sofort eine Situation vor, in der das Projekt viele Widgets verwendet, deren Anzeige je nach einem bestimmten internen Status variiert. Ich werde dieses Beispiel in der BLoC-Architektur betrachten und Entitäten aus der rxDart-Bibliothek verwenden.
Wir brauchen eine Schnittstelle, um den Durchflussregler zu schließen.
Eine Beimischung, mit der wir staatliche Unterstützung umsetzen.
Der logische Teil, der den Status des Widgets steuert. Lassen Sie sie einen Status festlegen, indem Sie die Methode aufrufen und nach 3 Sekunden in einen anderen ändern.
Und das Widget selbst, das auf eine Statusänderung reagiert. Stellen Sie sich vor, Sie erhalten die gewünschte logische Komponente mithilfe von Dependency Injection.
class ExampleWidget extends StatelessWidget { final bloc = di<HomePageBloc>(); @override Widget build(BuildContext context) { return StreamBuilder( stream: bloc.stateOut, builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
Auf Wunsch können wir dem Mix sogar hinzufügen, was geschrieben wurde, und nur die Implementierung der Builder-Methode über die Schnittstelle erfordern. Dies scheint mir jedoch bereits unnötig zu sein, da es unwahrscheinlich ist, dass das Projekt viele solcher einfachen Widgets enthält, da dies nur ein Beispiel war. Trotzdem kann der logische Teil der Zustandsunterstützungsfunktion mit dieser Beimischung problemlos zu jedem der BLoCs hinzugefügt werden.
Fazit
Der Mechanismus der Verwendung von Verunreinigungen schien mir ein ziemlich interessantes und flexibles Entwicklungswerkzeug zu sein, das es ermöglicht, eine einfache, verständliche und bequeme Architektur zu erstellen. Für mich selbst habe ich entschieden, dass dieses Tool in meinem Kit offensichtlich nicht überflüssig sein wird. Ich hoffe, dass es auch für Sie nützlich sein wird.
Ressourcen:
Eine Tour durch die DartspracheWikipedia