Redéfinition de noSuchMethod
Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy. Leçon 74 sur 110.
Lorsque vous appelez une méthode qui n'existe pas sur un objet, Dart lève normalement une NoSuchMethodError. Cependant, vous pouvez surcharger la méthode spéciale noSuchMethod() pour intercepter ces appels et les gérer de manière appropriée.
Pour utiliser noSuchMethod(), votre classe doit également implémenter une interface ou utiliser le typage dynamic.
La méthode reçoit un objet Invocation contenant des détails sur l'appel tenté :
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")
}L’objet Invocation fournit des informations utiles sur l’appel : memberName vous donne le nom de la méthode sous forme de Symbol, positionalArguments contient les arguments transmis, et isMethod vous indique s’il s’agissait d’un appel de méthode plutôt que d’un getter ou d’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); // géré
}Cette technique est utile pour créer des objets proxy, des classes mock pour les tests, ou pour construire des API flexibles qui répondent à des appels de méthodes arbitraires. Cependant, utilisez-la avec parcimonie car elle contourne la vérification de type à la compilation.
Défi
FacileConstruisons un journaliseur de méthodes qui intercepte et enregistre tous les appels de méthodes effectués sur un objet ! Vous allez créer une classe qui utilise noSuchMethod() pour capturer les informations sur les appels de méthodes non définies et y répondre intelligemment en fonction du nom de la méthode.
Vous allez organiser votre code en deux fichiers :
method_logger.dart: créez une classeMethodLoggerqui intercepte les appels aux méthodes non définies. Votre journaliseur doit redéfinirnoSuchMethod()pour :- Extraire le nom de la méthode de l'invocation (ce sera un Symbol comme
Symbol("methodName")— vous devrez le convertir en chaîne et n'en extraire que le nom) - Afficher le nom de la méthode et tous les arguments positionnels dans ce format :
Called: [methodName] with args: [arguments] - Renvoyer une réponse spéciale en fonction du nom de la méthode :
- Si le nom de la méthode contient
get, renvoyer la chaîne'data retrieved' - Si le nom de la méthode contient
save, renvoyer la chaîne'data saved' - Sinon, renvoyer la chaîne
'unknown action'
- Si le nom de la méthode contient
- Extraire le nom de la méthode de l'invocation (ce sera un Symbol comme
main.dart: importez votre journaliseur et montrez comment il gère différents appels de méthodes non définies. N'oubliez pas d'utiliser le typagedynamicafin que Dart autorise l'appel de méthodes qui n'existent pas :- Créez une instance de
MethodLoggerà l'aide d'une variable dynamique - Appelez
getUserData('Alice', 42)sur celle-ci et affichez le résultat renvoyé - Appelez
saveRecord('important')sur celle-ci et affichez le résultat renvoyé - Appelez
processItem()sur celle-ci (sans arguments) et affichez le résultat renvoyé
- Créez une instance de
Pour extraire le nom de la méthode d'un Symbol, vous pouvez le convertir en chaîne, puis extraire le nom situé entre les guillemets. Par exemple, Symbol("myMethod").toString() donne 'Symbol("myMethod")'.
Sortie attendue :
Called: getUserData with args: [Alice, 42]
data retrieved
Called: saveRecord with args: [important]
data saved
Called: processItem with args: []
unknown actionEssayez vous-même
import 'method_logger.dart';
void main() {
// TODO: Créer une instance de MethodLogger en utilisant le typage dynamique
// L'utilisation de dynamic permet d'appeler des méthodes qui n'existent pas au moment de la compilation
dynamic logger;
// TODO: Appeler getUserData('Alice', 42) et afficher le résultat
// TODO: Appeler saveRecord('important') et afficher le résultat
// TODO: Appeler processItem() sans argument et afficher le résultat
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesBibliothèques et importsIntroduction à la POOClasses vs objetsLe mot-clé thisMéthodesVariables d’instanceBases des constructeursRécapitulatif - Calculatrice simple4Sécurité face aux valeurs nulles
Introduction à la sécurité face aux valeurs nullesNullable vs Non-NullableLes opérateurs ? et !Mot-clé Late et sécurité face aux valeurs nullesOpérateurs sensibles à nullSécurité face aux valeurs nulles dans les classesRécapitulatif – Système de profil utilisateur7Classes abstraites et interfaces
Classes abstraitesMéthodes abstraitesInterfaces en DartInterfaces implicitesImplémenter ou étendreInterfaces multiplesRécapitulatif - Calculateur de formes10Collections et génériques
Vue d’ensemble des List, Set et MapCollections à typage sûrClasses génériquesMéthodes génériquesContraintes génériquesIterable et IteratorRécapitulatif – stockage générique2Constructeurs en Dart
Constructeur par défautConstructeurs nommésListes d'initialisationConstructeurs constantsConstructeurs factoryConstructeurs redirigésRécapitulatif - Constructeur de formes5Encapsulation
Membres publics vs privésLa convention du préfixe _Confidentialité au niveau de la bibliothèqueApprofondissement des getters et settersMasquage de l’informationRécapitulatif - Fiches des étudiants8Mixins
Introduction aux MixinsCréer des MixinsUtiliser plusieurs MixinsMot-clé on dans les MixinsMixin ou héritageMixin ou interfaceRécapitulatif - Système animal11Méthodes spéciales
Redéfinition de toString()Redéfinition de hashCode et ==Interface ComparableMéthode call()Redéfinition de noSuchMethodRécapitulatif - Collection personnalisée14Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FactoryPatron ObserverPatron Strategy3Propriétés des classes
Membres d’instance et statiquesChamps Final et ConstVariables différéesMéthodes et champs statiquesAccesseurs et mutateursRécapitulatif - Gestionnaire de compte bancaire6Héritage
Héritage de baseLe mot-clé superRedéfinition de méthodeL’annotation @overrideLe mot-clé de classe finalConstructeurs et héritageRécapitulatif – Hiérarchie des employés9Polymorphisme
Bases du polymorphismePolymorphisme via les interfacesVérification des types à l’exécutionLes opérateurs is et asMot-clé covariantRécapitulatif - Processeur de paiements12POO asynchrone
Futures et async/awaitNotions de base des StreamsContrôleurs de StreamsConstructeurs asynchronesAsynchrone dans les méthodes de classeRécapitulatif - récupérateur de données15Patrons de conception – Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode modèlePatron ÉtatPatron CompositePatron DépôtEntraînez-vous par vous-même : Compilateur Dart en ligne