Laut diesem Artikel ist es in Dart möglich, ein Non zu definieren -abstract-Klasse, um eine abstrakte (oder nicht implementierte) Methode zu haben. Die abstrakte Methode verursacht eine Warnung, verhindert jedoch nicht die Instanziierung.
Was ist der Zweck der Deklaration einer abstrakten Methode in einer nicht-abstrakten (oder konkreten) Klasse in Dart? Warum sollte Dart so arbeiten?
Die Spezifikation ist eigentlich sehr explizit, abstrakte Methoden in einer konkreten Klasse zu deklarieren:
Es ist eine statische Warnung , wenn ein abstraktes Mitglied m deklariert oder in einer konkreten Klasse geerbt ist
Wir möchten warnen , wenn eine eine konkrete Klasse mit abstrakten Mitgliedern deklariert.
Es ist eine statische Warnung , wenn eine konkrete Klasse über ein abstraktes Mitglied verfügt ( deklariert oder geerbt).
Sie haben keinen beabsichtigten Zweck dafür , weshalb sie Warnungen ausgeben. Wenn Sie mit Java vertraut sind: Es ähnelt über ein Objekt auf ein statisches Mitglied zugreifen , was ebenfalls sinnlos ist und eine Warnung auslöst.
Was die Kompilierung betrifft, verwendet Dart ein optionales Typsystem , was bedeutet, dass Tipp-Konzepte dies nicht beeinflussen sollten die Semantik der Sprache, und das ist einfach, was Dart erzwingt:
Der Zweck einer abstrakten Methode besteht darin, eine Deklaration für Zwecke wie Typprüfung und -reflexion bereitzustellen.
Der statische Prüfer meldet einige Verstöße gegen die Typregeln, aber solche Verstöße brechen die Kompilierung nicht ab oder verhindern die Ausführung.
Mit einer abstrakten Methode in einer konkreten Klasse können Sie die Typ-Signatur für eine Methode angeben, die stattdessen über noSuchMethod()
implementiert wird. Wenn Sie eine noSuchMethod()
-Implementierung bereitstellen, wird auch die Warnung stummgeschaltet.
Im strong-Modus führt eine abstrakte Methode in einer konkreten Klasse zu einem Fehler, es sei denn, die Klasse implementiert auch die Schnittstelle noSuchMethod()
.
Kurz gesagt besteht der Zweck von abstrakten Methoden in einer konkreten Klasse darin, Typensignaturen für noSuchMethod()
Implementierungen bereitzustellen. Dies vermeidet Warnungen für den Aufruf einer unbekannten Methode und im starken Modus (dies ist der Standardwert für dartdevc
, und wird zuerst der Standard und dann obligatorisch für Dart 2.0) diese Typ-Signaturen sind für Code mit noSuchMethod()
sogar zu kompilieren, es sei denn, das Ziel ist vom Typ dynamic
.
Beispiel:
%Vor% Wenn wir a.f()
durch (sagen wir) a.f(0)
ersetzen, führt dies zu einem Fehler (im starken Modus), dass die Methode mit der falschen Anzahl von Parametern aufgerufen wurde. Wenn wir die Deklaration void f()
weglassen, erhalten wir einen Fehler, dass A
keine Methode f()
hat. Wenn wir die noSuchMethod()
-Implementierung weglassen, lautet die Beschwerde, dass f()
keinen Methodenkörper hat, obwohl A
nicht abstrakt ist.
Der folgende Code bietet ein realistischeres Beispiel:
%Vor% In diesem Beispiel wird ein Debugging-Decorator für List<T>
erstellt, der alle Methodenaufrufe anzeigt. Wir verwenden implements List<T>
, um die gesamte Listenoberfläche einzubinden und Dutzende von abstrakten Methoden zu erben. Dies würde normalerweise zu Warnungen (oder im starken Modus, Fehlern) führen, wenn dartanalyzer
ausgeführt wird, da uns Implementierungen für alle diese Methoden fehlen, die normalerweise von List<T>
bereitgestellt werden. Wenn eine noSuchMethod()
-Implementierung bereitgestellt wird, werden diese Warnungen / Fehler unterdrückt.
Obwohl wir alle 50+ Methoden auch manuell umbrechen konnten, wäre das eine Menge Tipparbeit. Der obige Ansatz funktioniert auch dann, wenn neue Methoden zur Listenschnittstelle hinzugefügt werden, ohne dass wir unseren Code ändern müssen.
Anwendungsfälle zum expliziten Auflisten von Methoden in einer konkreten Klasse sind seltener, können aber auch auftreten. Ein Beispiel wäre die Hinzufügung von Getter oder Setter zu einem solchen Debugging-Decorator, der es uns ermöglicht, Instanzvariablen des Delegaten zu inspizieren oder zu setzen. Wir müssen sie trotzdem zur Oberfläche hinzufügen, um Warnungen und Fehler bei ihrer Verwendung zu vermeiden. Die Implementierung noSuchMethod()
kann sie dann mit getField()
und setField()
implementieren. Hier ist eine Variante des vorherigen Beispiels, die Stacks anstelle von Listen verwendet:
Beachten Sie, dass die abstrakte Deklaration des Getters _data
entscheidend für die Typprüfung ist. Wenn wir es entfernen würden, würden wir auch ohne starken Modus eine Warnung erhalten, und im starken Modus (z. B. mit dartdevc
oder dartanalyzer --strong
) wird es fehlschlagen: