Méthodes d'extension
Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 83 sur 110.
Parfois, vous souhaitez ajouter des fonctionnalités à une classe que vous ne possédez pas - comme les types intégrés String ou int de Dart. Vous ne pouvez pas modifier leur code source, et l'héritage n'est d'aucune aide avec les classes finales. C'est là qu'interviennent les méthodes d'extension.
Les extensions vous permettent d'ajouter de nouvelles méthodes à des types existants sans les modifier ni créer de sous-classes :
extension StringExtras on String {
String reverse() {
return split('').reversed.join('');
}
bool get isPalindrome {
var cleaned = toLowerCase().replaceAll(' ', '');
return cleaned == cleaned.split('').reversed.join('');
}
}
void main() {
print('hello'.reverse()); // olleh
print('radar'.isPalindrome); // true
}La syntaxe est extension ExtensionName on Type. À l'intérieur, vous définissez des méthodes et des getters tout comme dans une classe ordinaire. Une fois définies, ces méthodes apparaissent sur toutes les instances de ce type comme si elles étaient intégrées.
Les extensions fonctionnent sur n'importe quel type, y compris vos propres classes et les types génériques :
extension IntExtras on int {
int squared() => this * this;
}
extension ListExtras<T> on List<T> {
T? get secondOrNull => length >= 2 ? this[1] : null;
}
void main() {
print(5.squared()); // 25
print([1, 2, 3].secondOrNull); // 2
}Remarquez qu'à l'intérieur d'une extension, this fait référence à l'instance sur laquelle la méthode est appelée. Les extensions sont un moyen propre d'améliorer les types existants tout en gardant votre code organisé et lisible.
Défi
FacileAméliorons les types intégrés de Dart avec des fonctionnalités utiles en utilisant des méthodes d'extension ! Vous allez créer des extensions qui ajoutent des méthodes pratiques aux types String et List, puis les utiliser dans votre fichier principal.
Vous organiserez votre code en deux fichiers :
extensions.dart: Créez deux extensions qui ajoutent de nouvelles capacités aux types existants :- Une extension nommée
StringUtilssurStringavec :- Une méthode
countVowels()qui retourne le nombre de voyelles (a, e, i, o, u - insensible à la casse) dans la chaîne - Un getter
initialsqui retourne la première lettre de chaque mot (séparé par des espaces), jointes ensemble et en majuscules. Par exemple,"hello world"devient"HW"
- Une méthode
- Une extension nommée
ListUtils<T>surList<T>avec :- Une méthode
safeGet(int index)qui retourne l'élément à l'index s'il existe, ounullsi l'index est hors limites - Un getter
hasMultiplequi retournetruesi la liste contient plus d'un élément
- Une méthode
- Une extension nommée
main.dart: Importez vos extensions et faites-en la démonstration :- Créez une chaîne
"Object Oriented Programming"et affichez son nombre de voyelles au format :Vowels: [count] - Affichez les initiales de cette même chaîne au format :
Initials: [initials] - Créez une liste d'entiers
[10, 20, 30] - Affichez le résultat de
safeGet(1)au format :Element at 1: [value] - Affichez le résultat de
safeGet(5)au format :Element at 5: [value] - Affichez si la liste a plusieurs éléments au format :
Has multiple: [true/false]
- Créez une chaîne
N'oubliez pas qu'à l'intérieur d'une extension, this fait référence à l'instance sur laquelle la méthode est appelée. Vos extensions donneront l'impression que ces types possèdent ces méthodes de manière native !
Sortie attendue :
Vowels: 9
Initials: OOP
Element at 1: 20
Element at 5: null
Has multiple: trueAide-mémoire
Les méthodes d'extension vous permettent d'ajouter de nouvelles fonctionnalités à des types existants sans modifier leur code source ni utiliser l'héritage.
La syntaxe pour créer une extension est extension ExtensionName on Type :
extension StringExtras on String {
String reverse() {
return split('').reversed.join('');
}
bool get isPalindrome {
var cleaned = toLowerCase().replaceAll(' ', '');
return cleaned == cleaned.split('').reversed.join('');
}
}Une fois définies, les méthodes d'extension peuvent être appelées sur des instances de ce type comme s'il s'agissait de méthodes intégrées :
print('hello'.reverse()); // olleh
print('radar'.isPalindrome); // trueLes extensions fonctionnent sur n'importe quel type, y compris les types intégrés, vos propres classes et les types génériques :
extension IntExtras on int {
int squared() => this * this;
}
extension ListExtras<T> on List<T> {
T? get secondOrNull => length >= 2 ? this[1] : null;
}
print(5.squared()); // 25
print([1, 2, 3].secondOrNull); // 2À l'intérieur d'une extension, this fait référence à l'instance sur laquelle la méthode est appelée.
Essayez vous-même
import 'extensions.dart';
void main() {
// Créer la chaîne de caractères
String text = "Object Oriented Programming";
// TODO: Afficher le nombre de voyelles en utilisant countVowels()
// Format : Vowels: [count]
// TODO: Afficher les initiales en utilisant le getter initials
// Format : Initials: [initials]
// Créer la liste d'entiers
List<int> numbers = [10, 20, 30];
// TODO: Afficher le résultat de safeGet(1)
// Format : Element at 1: [value]
// TODO: Afficher le résultat de safeGet(5)
// Format : Element at 5: [value]
// TODO: Afficher si la liste contient plusieurs éléments
// Format : Has multiple: [true/false]
}
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érique13Concepts avancés de la POO
Composition vs HéritageMéthodes d'extensionClasses appelablesClasses scellées (Dart 3)Records (Dart 3)Patterns et Matching (3.0)Enums avec méthodes2Les 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