noSuchMethod überschreiben
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 74 von 110.
Wenn Sie eine Methode aufrufen, die für ein Objekt nicht existiert, wirft Dart normalerweise einen NoSuchMethodError. Sie können jedoch die spezielle noSuchMethod()-Methode überschreiben, um diese Aufrufe abzufangen und sie angemessen zu behandeln.
Um noSuchMethod() zu verwenden, muss Ihre Klasse auch ein Interface implementieren oder dynamic Typisierung verwenden.
Die Methode erhält ein Invocation-Objekt, das Details über den versuchten Aufruf enthält:
class Flexible {
@override
dynamic noSuchMethod(Invocation invocation) {
var methodName = invocation.memberName.toString();
print('Called: $methodName');
return null;
}
}
void main() {
dynamic obj = Flexible();
obj.anyMethod(); // Called: Symbol("anyMethod")
obj.anotherOne(42); // Called: Symbol("anotherOne")
}Das Invocation-Objekt bietet nützliche Informationen über den Aufruf – memberName gibt Ihnen den Methodennamen als Symbol zurück, positionalArguments enthält die übergebenen Argumente, und isMethod gibt an, ob es sich um einen Methodenaufruf im Gegensatz zu einem Getter oder Setter handelte.
class Logger {
@override
dynamic noSuchMethod(Invocation invocation) {
print('Method: ${invocation.memberName}');
print('Args: ${invocation.positionalArguments}');
return 'handled';
}
}
void main() {
dynamic log = Logger();
var result = log.save('data', 123);
print(result); // verarbeitet
}Diese Technik ist nützlich für die Erstellung von Proxy-Objekten, Mock-Klassen für Tests oder den Aufbau flexibler APIs, die auf beliebige Methodenaufrufe reagieren. Verwenden Sie sie jedoch sparsam, da sie die Typprüfung zur Kompilierzeit umgeht.
Aufgabe
EinfachLassen Sie uns einen Methoden-Logger erstellen, der alle Methodenaufrufe an einem Objekt abfängt und aufzeichnet! Sie werden eine Klasse erstellen, die noSuchMethod() verwendet, um Informationen über nicht definierte Methodenaufrufe zu erfassen und intelligent basierend auf dem Methodennamen zu reagieren.
Sie werden Ihren Code in zwei Dateien organisieren:
method_logger.dart: Erstellen Sie eine KlasseMethodLogger, die Aufrufe von nicht definierten Methoden abfängt. Ihr Logger solltenoSuchMethod()überschreiben, um:- Den Methodennamen aus dem Aufruf zu extrahieren (es wird ein Symbol wie
Symbol("methodName")sein - Sie müssen es in einen String umwandeln und nur den Namen extrahieren) - Den Methodennamen und alle Positionsargumente in diesem Format auszugeben:
Called: [methodName] with args: [arguments] - Eine spezielle Antwort basierend auf dem Methodennamen zurückzugeben:
- Wenn der Methodenname
getenthält, geben Sie den String'data retrieved'zurück - Wenn der Methodenname
saveenthält, geben Sie den String'data saved'zurück - Andernfalls geben Sie den String
'unknown action'zurück
- Wenn der Methodenname
- Den Methodennamen aus dem Aufruf zu extrahieren (es wird ein Symbol wie
main.dart: Importieren Sie Ihren Logger und demonstrieren Sie, wie er verschiedene nicht definierte Methodenaufrufe verarbeitet. Denken Sie daran, diedynamicTypisierung zu verwenden, damit Dart den Aufruf von Methoden erlaubt, die nicht existieren:- Erstellen Sie eine
MethodLoggerInstanz unter Verwendung einer dynamischen Variable - Rufen Sie
getUserData('Alice', 42)darauf auf und geben Sie das zurückgegebene Ergebnis aus - Rufen Sie
saveRecord('important')darauf auf und geben Sie das zurückgegebene Ergebnis aus - Rufen Sie
processItem()darauf auf (ohne Argumente) und geben Sie das zurückgegebene Ergebnis aus
- Erstellen Sie eine
Um den Methodennamen aus einem Symbol zu extrahieren, können Sie es in einen String umwandeln und dann den Namen zwischen den Anführungszeichen parsen. Zum Beispiel ergibt Symbol("myMethod").toString() den Wert 'Symbol("myMethod")'.
Erwartete Ausgabe:
Called: getUserData with args: [Alice, 42]
data retrieved
Called: saveRecord with args: [important]
data saved
Called: processItem with args: []
unknown actionSpickzettel
Die Methode noSuchMethod() ermöglicht es Ihnen, Aufrufe von Methoden abzufangen, die für ein Objekt nicht existieren. Um sie zu verwenden, muss Ihre Klasse dynamic-Typisierung verwenden oder ein Interface implementieren.
Überschreiben Sie noSuchMethod(), um undefinierte Methodenaufrufe zu behandeln:
class Flexible {
@override
dynamic noSuchMethod(Invocation invocation) {
var methodName = invocation.memberName.toString();
print('Called: $methodName');
return null;
}
}
void main() {
dynamic obj = Flexible();
obj.anyMethod(); // Called: Symbol("anyMethod")
obj.anotherOne(42); // Called: Symbol("anotherOne")
}Das Invocation-Objekt liefert Informationen über den Aufruf:
memberName- der Methodenname als SymbolpositionalArguments- die an die Methode übergebenen ArgumenteisMethod- gibt an, ob es sich um einen Methodenaufruf im Gegensatz zu einem Getter oder Setter handelt
class Logger {
@override
dynamic noSuchMethod(Invocation invocation) {
print('Method: ${invocation.memberName}');
print('Args: ${invocation.positionalArguments}');
return 'handled';
}
}
void main() {
dynamic log = Logger();
var result = log.save('data', 123);
print(result); // behandelt
}Diese Technik ist nützlich für die Erstellung von Proxy-Objekten, Mock-Klassen für Tests oder flexible APIs, sollte jedoch sparsam eingesetzt werden, da sie die Typprüfung zur Kompilierzeit umgeht.
Probier es selbst
import 'method_logger.dart';
void main() {
// TODO: Erstellen Sie eine MethodLogger-Instanz mit dynamischer Typisierung
// Die Verwendung von dynamic ermöglicht den Aufruf von Methoden, die zur Kompilierzeit nicht existieren
dynamic logger;
// TODO: Rufen Sie getUserData('Alice', 42) auf und geben Sie das Ergebnis aus
// TODO: Rufen Sie saveRecord('important') auf und geben Sie das Ergebnis aus
// TODO: Rufen Sie processItem() ohne Argumente auf und geben Sie das Ergebnis aus
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienBibliotheken & ImportsEinführung in die OOPKlassen vs. ObjekteDas this-SchlüsselwortMethodenInstanzvariablenKonstruktor-GrundlagenWiederholung – Einfacher Taschenrechner4Null-Sicherheit
Einführung in Null-SicherheitNullable vs. Non-NullableDie ? und ! OperatorenLate-Schlüsselwort & Null-SicherheitNull-aware OperatorenNull-Sicherheit in KlassenZusammenfassung – Benutzerprofil-System7Abstrakte Klassen & Interfaces
Abstrakte KlassenAbstrakte MethodenInterfaces in DartImplizite InterfacesImplementieren vs. ErweiternMehrfache InterfacesRückblick – Shape Calculator10Collections & Generics
Überblick über List, Set und MapTypsichere CollectionsGenerische KlassenGenerische MethodenGenerische ConstraintsIterable & IteratorZusammenfassung – Generische Speicherung13Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungExtension MethodsCallable ClassesSealed Classes (Dart 3)Records (Dart 3)Patterns & Matching (3.0)Enums mit Methoden16Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen2Konstruktoren in Dart
Standard-KonstruktorBenannte KonstruktorenInitialisierungslistenKonstante KonstruktorenFactory-KonstruktorenWeiterleitende KonstruktorenZusammenfassung – Shape Builder5Kapselung
Öffentliche vs. private MemberDie _ Präfix-KonventionSichtbarkeit auf Library-EbeneGetter & Setter im DetailInformation HidingRückblick – Schülerdatensätze8Mixins
Einführung in MixinsMixins erstellenMehrere Mixins verwendenDas on-Schlüsselwort in MixinsMixin vs. VererbungMixin vs. InterfaceZusammenfassung - Tiersystem11Spezielle Methoden
toString() überschreibenhashCode & == überschreibenComparable-Interfacecall()-MethodenoSuchMethod überschreibenZusammenfassung – Eigene Collection14Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterObserver-MusterStrategy-Muster3Klasseneigenschaften
Instanz- vs. statische MemberFinal & Const FelderLate-VariablenStatische Methoden & FelderGetter und SetterZusammenfassung – Bankkonto-Manager6Vererbung
Grundlagen der VererbungDas super-SchlüsselwortMethoden überschreibenDie @override-AnnotationDas final-Klassen-SchlüsselwortKonstruktoren & VererbungRückblick – Mitarbeiter-Hierarchie9Polymorphismus
Polymorphismus-GrundlagenPolymorphismus über InterfacesTypprüfung zur LaufzeitDie is & as OperatorenDas covariant SchlüsselwortZusammenfassung – Payment Processor