Méthodes abstraites
Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 44 sur 110.
Une méthode abstraite est une méthode déclarée à l'intérieur d'une classe abstraite qui n'a pas de corps. Elle définit la signature de la méthode mais laisse l'implémentation à chaque sous-classe. Toute classe qui étend la classe abstraite doit redéfinir toutes les méthodes abstraites, sinon elle sera également abstraite.
abstract class Animal {
// Méthode abstraite - pas de corps, doit être implémentée par les sous-classes
String makeSound();
// Méthode concrète - possède un corps, partagée par toutes les sous-classes
void breathe() {
print('Breathing...');
}
}
class Dog extends Animal {
@override
String makeSound() {
return 'Woof!'; // Doit fournir une implémentation
}
}
class Cat extends Animal {
@override
String makeSound() {
return 'Meow!'; // Implémentation différente, même signature
}
}Si une sous-classe oublie d'implémenter une méthode abstraite, Dart vous donnera une erreur de compilation. C'est tout l'intérêt : les méthodes abstraites imposent un contrat. Chaque sous-classe est garantie d'avoir cette méthode, vous pouvez donc l'appeler en toute sécurité sur n'importe quelle instance du type abstrait.
// Vous pouvez utiliser le type abstrait comme type de variable
Animal a = Dog();
print(a.makeSound()); // Ouaf !
Animal b = Cat();
print(b.makeSound()); // Miaou !Les méthodes abstraites sont différentes des méthodes concrètes dans une classe abstraite. Les méthodes concrètes ont un corps et sont héritées telles quelles. Les méthodes abstraites n'ont pas de corps et doivent être redéfinies.
Vous pouvez mélanger les deux dans la même classe abstraite pour partager certains comportements tout en forçant les sous-classes à définir les leurs pour d'autres.
| Caractéristique | Méthode abstraite | Méthode concrète |
|---|---|---|
| Possède un corps | Non | Oui |
| Doit être redéfinie | Oui | Non |
| Objectif | Imposer un contrat | Partager un comportement |
| Emplacement | Classe abstraite uniquement | N'importe quelle classe |
Défi
FacileConstruisons un calculateur de formes qui démontre les méthodes abstraites en action. Vous allez définir une classe abstraite avec des méthodes abstraites que chaque forme doit implémenter différemment, puis utiliser ces formes via une interface commune.
Vous organiserez votre code en quatre fichiers :
shape.dart: Définissez une classe abstraiteShapeavec un champfinalcolor(String) et un constructeur qui l'initialise. Déclarez deux méthodes abstraites :double area()etdouble perimeter(). Ajoutez également une méthode concrètedescribe()qui afficheA [color] shape with area: [area] and perimeter: [perimeter]. Parce quearea()etperimeter()sont abstraites, chaque sous-classe fournira son propre calcul, maisdescribe()fonctionne pour toutes sans être redéfinie.circle.dart: Créez une classeCirclequi étendShape. Elle possède un champfinalradius(double). Son constructeur prendcoloretradiuset passecoloràsuper. Implémentezarea()pour retourner3.14 * radius * radiusetperimeter()pour retourner2 * 3.14 * radius.rectangle.dart: Créez une classeRectanglequi étendShape. Elle possède des champsfinalwidthetheight(tous deux double). Son constructeur prendcolor,widthetheightet passecoloràsuper. Implémentezarea()pour retournerwidth * heightetperimeter()pour retourner2 * (width + height).main.dart: Importez tous les fichiers. Créez unCircleavec la couleur'red'et un rayon de5.0, et unRectangleavec la couleur'blue', une largeur de4.0et une hauteur de6.0. Appelezdescribe()sur chaque forme. Ensuite, créez uneList<Shape>contenant les deux formes, parcourez la liste et affichezArea: [area]pour chaque forme.
Sortie attendue :
A red shape with area: 78.5 and perimeter: 31.400000000000002
A blue shape with area: 24.0 and perimeter: 20.0
Area: 78.5
Area: 24.0Aide-mémoire
Une méthode abstraite est une méthode déclarée dans une classe abstraite sans corps. Les sous-classes doivent la redéfinir pour fournir leur propre implémentation.
abstract class Animal {
// Méthode abstraite - pas de corps
String makeSound();
// Méthode concrète - possède un corps
void breathe() {
print('Breathing...');
}
}Les sous-classes doivent implémenter toutes les méthodes abstraites :
class Dog extends Animal {
@override
String makeSound() {
return 'Woof!';
}
}
class Cat extends Animal {
@override
String makeSound() {
return 'Meow!';
}
}Vous pouvez utiliser le type abstrait comme type de variable :
Animal a = Dog();
print(a.makeSound()); // Woof!
Animal b = Cat();
print(b.makeSound()); // Meow!| Caractéristique | Méthode abstraite | Méthode concrète |
|---|---|---|
| Possède un corps | Non | Oui |
| Doit être redéfinie | Oui | Non |
| Objectif | Imposer un contrat | Partager un comportement |
| Où | Classe abstraite uniquement | N'importe quelle classe |
Essayez vous-même
import 'shape.dart';
import 'circle.dart';
import 'rectangle.dart';
void main() {
// TODO: Créer un Circle avec la couleur 'red' et un rayon de 5.0
// TODO: Créer un Rectangle avec la couleur 'blue', une largeur de 4.0 et une hauteur de 6.0
// TODO: Appeler describe() sur le cercle
// TODO: Appeler describe() sur le rectangle
// TODO: Créer une List<Shape> contenant les deux formes
// TODO: Parcourir la liste et afficher "Area: [area]" pour chaque forme
}
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