L'annotation @override
Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 39 sur 110.
L'annotation @override est un marqueur de bonne pratique qui indique à Dart (et aux autres développeurs) que vous remplacez intentionnellement une méthode d'une classe parente. Bien que la redéfinition de méthode fonctionne sans elle, l'utilisation de @override ajoute un filet de sécurité important.
class Animal {
String name;
Animal(this.name);
void speak() {
print('$name makes a sound');
}
}
class Dog extends Animal {
Dog(String name) : super(name);
@override
void speak() {
print('$name barks: Woof!');
}
}L'annotation offre deux avantages clés. Premièrement, elle documente clairement votre intention : toute personne lisant le code sait immédiatement que cette méthode existe dans la classe parente. Deuxièmement, l'analyseur de Dart vous avertira si la méthode parente n'existe pas réellement, ce qui permet de détecter tôt les fautes de frappe et les erreurs de refactorisation.
Considérez ce qui se passe si vous orthographiez mal le nom de la méthode sans @override :
class Cat extends Animal {
Cat(String name) : super(name);
void speek() { // Faute de frappe ! Pas d'avertissement sans @override
print('$name meows');
}
}Sans l'annotation, Dart suppose que vous créez une nouvelle méthode appelée speek(). Avec @override, l'analyseur signalerait immédiatement qu'une telle méthode n'existe pas dans la classe parente. Cette simple annotation évite des bugs subtils qui peuvent être difficiles à traquer plus tard.
Défi
FacileConstruisons un système de lecteur multimédia qui démontre l'importance de l'annotation @override lors de la personnalisation d'un comportement hérité. Vous allez créer différents types de médias qui lisent chacun du contenu à leur manière.
Vous organiserez votre code en deux fichiers :
media.dart: Définissez votre hiérarchie de médias ici :- Une classe
Mediaavec une propriétéString title, un constructeur qui prend le titre, et une méthodeplay()qui affichePlaying: [title] - Une classe
Songqui étendMediaet ajoute une propriétéString artist. Utilisez l'annotation@overrideet surchargezplay()pour afficherPlaying song: [title] by [artist] - Une classe
Videoqui étendMediaet ajoute une propriétéint duration(en secondes). Utilisez@overrideet surchargezplay()pour appeler d'abord la version du parent avecsuper.play(), puis afficherDuration: [duration] seconds
- Une classe
main.dart: Importez votre fichier média et démontrez les méthodes surchargées :- Créez un objet
Mediaavec le titre'Generic Content'et appelezplay() - Affichez une ligne vide
- Créez un
Songavec le titre'Imagine'et l'artiste'John Lennon', puis appelezplay() - Affichez une ligne vide
- Créez une
Videoavec le titre'Dart Tutorial'et la durée360, puis appelezplay()
- Créez un objet
L'annotation @override documente votre intention et aide à détecter les erreurs. Si vous aviez accidentellement mal orthographié play() en plya(), l'annotation vous avertirait qu'aucune méthode de ce type n'existe dans la classe parente.
Sortie attendue :
Playing: Generic Content
Playing song: Imagine by John Lennon
Playing: Dart Tutorial
Duration: 360 secondsAide-mémoire
L'annotation @override marque les méthodes qui remplacent intentionnellement une méthode de la classe parente. Bien qu'elle soit facultative, elle apporte sécurité et clarté.
class Animal {
String name;
Animal(this.name);
void speak() {
print('$name makes a sound');
}
}
class Dog extends Animal {
Dog(String name) : super(name);
@override
void speak() {
print('$name barks: Woof!');
}
}Avantages de @override :
- Documente l'intention - montre que la méthode existe dans la classe parente
- Détecte les erreurs - l'analyseur de Dart avertit si la méthode parente n'existe pas, évitant ainsi les fautes de frappe
Sans @override, les fautes de frappe créent de nouvelles méthodes au lieu de signaler des erreurs :
class Cat extends Animal {
Cat(String name) : super(name);
void speek() { // Une faute de frappe crée une nouvelle méthode sans avertissement
print('$name meows');
}
}Vous pouvez appeler la version du parent en utilisant super :
@override
void play() {
super.play(); // Appelle d'abord la méthode parente
print('Additional behavior');
}Essayez vous-même
import 'media.dart';
void main() {
// TODO: Créer un objet Media avec le titre 'Generic Content' et appeler play()
// TODO: Afficher une ligne vide
// TODO: Créer un Song avec le titre 'Imagine' et l'artiste 'John Lennon', puis appeler play()
// TODO: Afficher une ligne vide
// TODO: Créer un Video avec le titre 'Dart Tutorial' et la durée 360, puis appeler play()
}
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
1Les bases de la POO
Fichiers externesBibliothèques et importsIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesVariables d'instanceBases des constructeursRécapitulatif - Calculatrice simple4Null Safety
Introduction à la Null SafetyNullable vs Non-NullableLes opérateurs ? et !Le mot-clé late et la Null SafetyLes opérateurs Null-AwareLa Null Safety dans les classesRécapitulatif - Système de profil utilisateur7Classes abstraites et Interfaces
Classes abstraitesMéthodes abstraitesInterfaces en DartInterfaces implicitesImplémentation vs ExtensionInterfaces multiplesRécapitulatif - Calculateur de formes10Collections et Génériques
Aperçu des List, Set et MapCollections Type-SafeClasses génériquesMéthodes génériquesContraintes de généricitéIterable & IteratorRécapitulatif - Stockage générique2Les constructeurs en Dart
Constructeur par défautConstructeurs nommésListes d'initialisationConstructeurs constantsConstructeurs factoryConstructeurs de redirectionRécapitulatif - Shape Builder5Encapsulation
Membres publics vs privésLa convention du préfixe _Visibilité au niveau de la bibliothèqueApprofondissement des Getters & SettersMasquage d'informationsRécapitulatif - Dossiers d'étudiants8Mixins
Introduction aux MixinsCréation de MixinsUtilisation de plusieurs MixinsLe mot-clé on dans les MixinsMixin vs HéritageMixin vs InterfaceRécapitulatif - Système Animal11Méthodes spéciales
Redéfinition de toString()Redéfinition de hashCode & ==Interface ComparableMéthode call()Redéfinition de noSuchMethodRécapitulatif - Collection personnalisée14Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie3Propriétés de classe
Membres d'instance vs statiquesChamps Final & ConstVariables LateMéthodes et champs statiquesGetters et SettersRécapitulatif - Gestionnaire de compte bancaire6Héritage
Bases de l'héritageLe mot-clé superRedéfinition de méthodeL'annotation @overrideLe mot-clé final pour les classesConstructeurs et héritageRécapitulatif - Hiérarchie des employés9Polymorphisme
Bases du polymorphismePolymorphisme via les interfacesVérification de type à l'exécutionLes opérateurs is & asMot-clé covariantRécapitulatif - Processeur de paiement12POO Asynchrone
Futures & async/awaitBases des StreamsStream ControllersConstructeurs asynchronesL'asynchrone dans les méthodes de classeRécapitulatif - Data Fetcher15Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository