Menu
Coddy logo textTech

Nadpisanie noSuchMethod

Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 74 z 110.

Gdy wywołasz metodę, która nie istnieje w obiekcie, Dart zwykle zgłasza NoSuchMethodError. Możesz jednak nadpisać specjalną metodę noSuchMethod(), aby przechwytywać te wywołania i obsługiwać je w odpowiedni sposób.

Aby używać noSuchMethod(), Twoja klasa musi również implementować interfejs lub korzystać z typowania dynamic.

Metoda otrzymuje obiekt Invocation zawierający szczegóły dotyczące próby wywołania:

class Flexible {
  @override
  dynamic noSuchMethod(Invocation invocation) {
    var methodName = invocation.memberName.toString();
    print('Called: $methodName');
    return null;
  }
}

void main() {
  dynamic obj = Flexible();
  obj.anyMethod();      // Wywołano: Symbol("anyMethod")
  obj.anotherOne(42);   // Wywołano: Symbol("anotherOne")
}

Obiekt Invocation dostarcza przydatnych informacji o wywołaniu — memberName podaje nazwę metody jako symbol, positionalArguments zawiera przekazane argumenty, a isMethod informuje, czy było to wywołanie metody, czy getter lub setter.

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
}

Ta technika jest przydatna przy tworzeniu obiektów proxy, klas atrap do testowania lub elastycznych interfejsów API, które reagują na dowolne wywołania metod. Używaj jej jednak oszczędnie, ponieważ omija kontrolę typów w czasie kompilacji.

challenge icon

Wyzwanie

Łatwy

Zbudujmy rejestrator metod, który przechwytuje i zapisuje wszystkie wywołania metod wykonywane na obiekcie! Utworzysz klasę, która używa noSuchMethod() do przechwytywania informacji o wywołaniach niezdefiniowanych metod i inteligentnego reagowania na podstawie nazwy metody.

Podzielisz kod na dwa pliki:

  • method_logger.dart: Utwórz klasę MethodLogger, która przechwytuje wywołania niezdefiniowanych metod. Twój rejestrator powinien nadpisywać noSuchMethod(), aby:
    • Wyodrębnić nazwę metody z wywołania (będzie to Symbol w rodzaju Symbol("methodName") — trzeba przekonwertować go na ciąg znaków i wyodrębnić samą nazwę)
    • Wypisać nazwę metody i wszystkie argumenty pozycyjne w tym formacie: Called: [methodName] with args: [arguments]
    • Zwrócić specjalną odpowiedź na podstawie nazwy metody:
      • Jeśli nazwa metody zawiera get, zwrócić ciąg znaków 'data retrieved'
      • Jeśli nazwa metody zawiera save, zwrócić ciąg znaków 'data saved'
      • W przeciwnym razie zwrócić ciąg znaków 'unknown action'
  • main.dart: Zaimportuj rejestrator i pokaż, jak obsługuje różne wywołania niezdefiniowanych metod. Pamiętaj, aby użyć typowania dynamic, aby Dart pozwolił na wywoływanie metod, które nie istnieją:
    • Utwórz instancję MethodLogger i przypisz ją do zmiennej typu dynamicznego
    • Wywołaj na niej getUserData('Alice', 42) i wypisz zwrócony wynik
    • Wywołaj na niej saveRecord('important') i wypisz zwrócony wynik
    • Wywołaj na niej processItem() (bez argumentów) i wypisz zwrócony wynik

Aby wyodrębnić nazwę metody z symbolu Symbol, możesz przekonwertować go na ciąg znaków, a następnie wyodrębnić nazwę znajdującą się między cudzysłowami. Na przykład Symbol("myMethod").toString() zwraca 'Symbol("myMethod")'.

Oczekiwany wynik:

Called: getUserData with args: [Alice, 42]
data retrieved
Called: saveRecord with args: [important]
data saved
Called: processItem with args: []
unknown action

Spróbuj swoich sił

import 'method_logger.dart';

void main() {
  // TODO: Utwórz instancję MethodLogger, używając typowania dynamicznego
  // Użycie dynamic pozwala wywoływać metody, które nie istnieją w czasie kompilacji
  dynamic logger;
  
  // TODO: Wywołaj getUserData('Alice', 42) i wypisz wynik
  
  // TODO: Wywołaj saveRecord('important') i wypisz wynik
  
  // TODO: Wywołaj processItem() bez argumentów i wypisz wynik
  
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Dart online