Metodi di estensione
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 83 di 110.
A volte vuoi aggiungere funzionalità a una classe che non possiedi, come i tipi integrati String o int di Dart. Non puoi modificare il loro codice sorgente e l’ereditarietà non è d’aiuto con le classi finali. È qui che entrano in gioco i metodi di estensione.
Le estensioni ti consentono di aggiungere nuovi metodi ai tipi esistenti senza modificarli o creare sottoclassi:
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 sintassi è extension ExtensionName on Type. Al suo interno, definisci metodi e getter proprio come in una classe normale. Una volta definiti, questi metodi sono disponibili su tutte le istanze di quel tipo, come se fossero integrati.
Le estensioni funzionano su qualsiasi tipo, incluse le tue classi e i tipi generici:
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
}Nota che all'interno di un'estensione, this si riferisce all'istanza su cui viene chiamato il metodo. Le estensioni sono un modo ordinato per arricchire i tipi esistenti mantenendo il codice organizzato e leggibile.
Sfida
FacileMiglioriamo i tipi integrati di Dart con funzionalità utili usando i metodi di estensione! Creerai estensioni che aggiungono metodi utili ai tipi String e List, per poi usarli nel file principale.
Organizzerai il codice in due file:
extensions.dart: crea due estensioni che aggiungono nuove funzionalità ai tipi esistenti:- Un'estensione chiamata
StringUtilssuStringcon:- Un metodo
countVowels()che restituisce il numero di vocali (a, e, i, o, u, senza distinzione tra maiuscole e minuscole) nella stringa - Un getter
initialsche restituisce la prima lettera di ogni parola (separata dagli spazi), unite e convertite in maiuscolo. Per esempio,"hello world"diventa"HW"
- Un metodo
- Un'estensione chiamata
ListUtils<T>suList<T>con:- Un metodo
safeGet(int index)che restituisce l'elemento all'indice se esiste, oppurenullse l'indice è fuori dai limiti - Un getter
hasMultipleche restituiscetruese la lista contiene più di un elemento
- Un metodo
- Un'estensione chiamata
main.dart: importa le tue estensioni e mostra come funzionano:- Crea la stringa
"Object Oriented Programming"e stampa il numero di vocali nel formato:Vowels: [count] - Stampa le iniziali della stessa stringa nel formato:
Initials: [initials] - Crea una lista di numeri interi
[10, 20, 30] - Stampa il risultato di
safeGet(1)nel formato:Element at 1: [value] - Stampa il risultato di
safeGet(5)nel formato:Element at 5: [value] - Stampa se la lista contiene più elementi nel formato:
Has multiple: [true/false]
- Crea la stringa
Ricorda che all'interno di un'estensione, this si riferisce all'istanza su cui viene chiamato il metodo. Le tue estensioni faranno sembrare che questi tipi abbiano già questi metodi integrati!
Output previsto:
Vowels: 9
Initials: OOP
Element at 1: 20
Element at 5: null
Has multiple: trueProvalo tu
import 'extensions.dart';
void main() {
// Crea la stringa
String text = "Object Oriented Programming";
// TODO: Stampa il numero di vocali usando countVowels()
// Formato: Vowels: [count]
// TODO: Stampa le iniziali usando il getter initials
// Formato: Initials: [initials]
// Crea la lista di numeri interi
List<int> numbers = [10, 20, 30];
// TODO: Stampa il risultato di safeGet(1)
// Formato: Element at 1: [value]
// TODO: Stampa il risultato di safeGet(5)
// Formato: Element at 5: [value]
// TODO: Stampa se la lista contiene più elementi
// Formato: Has multiple: [true/false]
}
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