Menu
Coddy logo textTech

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 eine Schnittstelle 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();      // Aufgerufen: Symbol("anyMethod")
  obj.anotherOne(42);   // Aufgerufen: Symbol("anotherOne")
}

Das Invocation-Objekt bietet nützliche Informationen über den Aufruf – memberName liefert Ihnen den Methodennamen als Symbol, 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);  // handled
}

Diese Technik ist nützlich für das Erstellen 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.

challenge icon

Aufgabe

Einfach

Lassen 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 MethodLogger-Klasse, die Aufrufe von nicht definierten Methoden abfängt. Ihr Logger sollte noSuchMethod() überschreiben, um:
    • Den Methodennamen aus der Invocation 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 get enthält, geben Sie den String 'data retrieved' zurück
      • Wenn der Methodenname save enthält, geben Sie den String 'data saved' zurück
      • Andernfalls geben Sie den String 'unknown action' zurück
  • main.dart: Importieren Sie Ihren Logger und demonstrieren Sie, wie er verschiedene nicht definierte Methodenaufrufe verarbeitet. Denken Sie daran, dynamic Typisierung zu verwenden, damit Dart das Aufrufen von Methoden erlaubt, die nicht existieren:
    • Erstellen Sie eine MethodLogger-Instanz 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

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 action

Probier es selbst

import 'method_logger.dart';

void main() {
  // TODO: Erstelle eine MethodLogger-Instanz unter Verwendung von dynamic Typisierung
  // Die Verwendung von dynamic ermöglicht den Aufruf von Methoden, die zur Kompilierzeit nicht existieren
  dynamic logger;
  
  // TODO: Rufe getUserData('Alice', 42) auf und gib das Ergebnis aus
  
  // TODO: Rufe saveRecord('important') auf und gib das Ergebnis aus
  
  // TODO: Rufe processItem() ohne Argumente auf und gib das Ergebnis aus
  
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung