Menu
Coddy logo textTech

noSuchMethod-Überschreibung

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

Lass uns einen Methoden-Logger erstellen, der alle Methodenaufrufe abfängt und aufzeichnet, die an einem Objekt vorgenommen werden! Du erstellst eine Klasse, die noSuchMethod() verwendet, um Informationen über Aufrufe nicht definierter Methoden zu erfassen und abhängig vom Methodennamen intelligent zu reagieren.

Du organisierst deinen Code in zwei Dateien:

  • method_logger.dart: Erstelle eine MethodLogger-Klasse, die Aufrufe nicht definierter Methoden abfängt. Dein Logger sollte noSuchMethod() überschreiben, um:
    • Den Methodennamen aus dem Aufruf zu extrahieren (er wird ein Symbol wie Symbol("methodName") sein – du musst es in einen String umwandeln und nur den Namen extrahieren)
    • Den Methodennamen und alle Positionsargumente in diesem Format auszugeben: Called: [methodName] with args: [arguments]
    • Abhängig vom Methodennamen eine spezielle Antwort zurückzugeben:
      • Wenn der Methodenname get enthält, gib den String 'data retrieved' zurück
      • Wenn der Methodenname save enthält, gib den String 'data saved' zurück
      • Andernfalls gib den String 'unknown action' zurück
  • main.dart: Importiere deinen Logger und demonstriere, wie er verschiedene Aufrufe nicht definierter Methoden verarbeitet. Denke daran, die Typisierung dynamic zu verwenden, damit Dart den Aufruf nicht vorhandener Methoden erlaubt:
    • Erstelle eine MethodLogger-Instanz mithilfe einer dynamischen Variable
    • Rufe getUserData('Alice', 42) auf ihr auf und gib das zurückgegebene Ergebnis aus
    • Rufe saveRecord('important') auf ihr auf und gib das zurückgegebene Ergebnis aus
    • Rufe processItem() auf ihr auf (ohne Argumente) und gib das zurückgegebene Ergebnis aus

Um den Methodennamen aus einem Symbol zu extrahieren, kannst du es in einen String umwandeln und anschließend den Namen zwischen den Anführungszeichen herausparsen. Zum Beispiel liefert 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

Übe selbstständig: Online-Dart-Compiler