Sovrascrittura di noSuchMethod
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 74 di 110.
Quando chiami un metodo che non esiste su un oggetto, Dart normalmente genera un NoSuchMethodError. Tuttavia, puoi eseguire l'override del metodo speciale noSuchMethod() per intercettare queste chiamate e gestirle in modo appropriato.
Per usare noSuchMethod(), la tua classe deve anche implementare un'interfaccia oppure usare la tipizzazione dynamic.
Il metodo riceve un oggetto Invocation che contiene i dettagli della chiamata tentata:
class Flexible {
@override
dynamic noSuchMethod(Invocation invocation) {
var methodName = invocation.memberName.toString();
print('Called: $methodName');
return null;
}
}
void main() {
dynamic obj = Flexible();
obj.anyMethod(); // Chiamato: Symbol("anyMethod")
obj.anotherOne(42); // Chiamato: Symbol("anotherOne")
}L'oggetto Invocation fornisce informazioni utili sulla chiamata: memberName ti dà il nome del metodo come Symbol, positionalArguments contiene gli argomenti passati e isMethod indica se si trattava di una chiamata a un metodo anziché a un getter o a un 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
}Questa tecnica è utile per creare oggetti proxy, classi mock per i test o API flessibili che rispondono a chiamate arbitrarie ai metodi. Tuttavia, usala con parsimonia, poiché aggira il controllo dei tipi in fase di compilazione.
Sfida
FacileCostruiamo un logger dei metodi che intercetta e registra qualsiasi chiamata a un metodo effettuata su un oggetto! Creerai una classe che usa noSuchMethod() per acquisire informazioni sulle chiamate a metodi non definiti e rispondere in modo intelligente in base al nome del metodo.
Organizzerai il codice in due file:
method_logger.dart: crea una classeMethodLoggerche intercetta le chiamate ai metodi non definiti. Il logger deve sovrascriverenoSuchMethod()per:- Estrarre il nome del metodo dalla chiamata (sarà un Symbol come
Symbol("methodName"): dovrai convertirlo in una stringa ed estrarre solo il nome) - Stampare il nome del metodo e gli eventuali argomenti posizionali in questo formato:
Called: [methodName] with args: [arguments] - Restituire una risposta speciale in base al nome del metodo:
- Se il nome del metodo contiene
get, restituisci la stringa'data retrieved' - Se il nome del metodo contiene
save, restituisci la stringa'data saved' - Altrimenti, restituisci la stringa
'unknown action'
- Se il nome del metodo contiene
- Estrarre il nome del metodo dalla chiamata (sarà un Symbol come
main.dart: importa il logger e mostra come gestisce varie chiamate a metodi non definiti. Ricorda di usare il tipodynamicaffinché Dart consenta di chiamare metodi che non esistono:- Crea un'istanza di
MethodLoggerusando una variabile di tipo dynamic - Chiamaci
getUserData('Alice', 42)e stampa il risultato restituito - Chiamaci
saveRecord('important')e stampa il risultato restituito - Chiamaci
processItem()(senza argomenti) e stampa il risultato restituito
- Crea un'istanza di
Per estrarre il nome del metodo da un Symbol, puoi convertirlo in una stringa e poi ricavare il nome racchiuso tra virgolette. Per esempio, Symbol("myMethod").toString() restituisce 'Symbol("myMethod")'.
Output previsto:
Called: getUserData with args: [Alice, 42]
data retrieved
Called: saveRecord with args: [important]
data saved
Called: processItem with args: []
unknown actionProvalo tu
import 'method_logger.dart';
void main() {
// TODO: Crea un'istanza di MethodLogger usando la tipizzazione dinamica
// L'uso di dynamic permette di chiamare metodi che non esistono in fase di compilazione
dynamic logger;
// TODO: Chiama getUserData('Alice', 42) e stampa il risultato
// TODO: Chiama saveRecord('important') e stampa il risultato
// TODO: Chiama processItem() senza argomenti e stampa il risultato
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniLibrerie e importazioniIntroduzione alla programmazione orientata agli oggettiClassi e oggettiLa parola chiave thisMetodiVariabili di istanzaFondamenti dei costruttoriRiepilogo - Calcolatrice semplice4Sicurezza dei valori null
Introduzione alla sicurezza dei valori nullNullable e non nullableGli operatori ? e !La keyword late e la sicurezza dei valori nullOperatori null-awareSicurezza dei valori null nelle classiRiepilogo - Sistema di profili utente7Classi astratte e interfacce
Classi astratteMetodi astrattiInterfacce in DartInterfacce impliciteImplementare vs estendereInterfacce multipleRiepilogo - Calcolatore di forme10Collezioni e generici
Panoramica di List, Set e MapCollezioni sicure rispetto ai tipiClassi genericheMetodi genericiVincoli sui genericiIterable e IteratorRiepilogo - Archiviazione generica13Concetti avanzati di OOP
Composizione vs ereditarietàMetodi di estensioneClassi chiamabiliClassi sealed (Dart 3)Record (Dart 3)Pattern e matching (3.0)Enum con metodi16Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e Utente2I costruttori in Dart
Costruttore predefinitoCostruttori con nomeListe di inizializzazioneCostruttori costantiCostruttori factoryCostruttori di reindirizzamentoRiepilogo - Crea forme5Incapsulamento
Membri pubblici e privatiConvenzione del prefisso _Visibilità a livello di libreriaApprofondimento su getter e setterNascondimento delle informazioniRiepilogo - Registri degli studenti8Mixin
Introduzione ai MixinCreare MixinUsare più MixinParola chiave on nei MixinMixin vs ereditarietàMixin vs interfacciaRiepilogo - Sistema animale11Metodi speciali
Sovrascrittura di toString()Sovrascrittura di hashCode e ==Interfaccia ComparableMetodo call()Sovrascrittura di noSuchMethodRiepilogo - Collezione personalizzata14Modelli di progettazione Parte 1
Introduzione ai modelli di progettazioneSingletonFactoryObserverStrategy3Proprietà delle classi
Membri di istanza e staticiCampi final e constVariabili lateMetodi e campi staticiGetter e setterRiepilogo - Gestore di conti bancari6Ereditarietà
Ereditarietà di baseLa parola chiave superOverride dei metodiL’annotazione @overrideLa parola chiave final per le classiCostruttori ed ereditarietàRiepilogo - Gerarchia dei dipendenti9Polimorfismo
Fondamenti di polimorfismoPolimorfismo tramite interfacceControllo del tipo a runtimeGli operatori is e asParola chiave covariantRiepilogo - Elaboratore di pagamenti12OOP asincrona
Future e async/awaitNozioni di base sugli streamController degli streamCostruttori asincroniAsync nei metodi di classeRiepilogo - Recupero dei dati15Pattern di progettazione Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern RepositoryEsercitati da solo: Compilatore Dart online