Classi generiche
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 65 di 110.
Hai visto come le raccolte integrate di Dart, come List<String>, usano parametri di tipo. Ora è il momento di creare le tue classi generiche, che funzionano con qualsiasi tipo tu specifichi.
Una classe generica usa un parametro di tipo (in genere T) come segnaposto per il tipo effettivo che verrà fornito quando si crea un'istanza:
class Box<T> {
T content;
Box(this.content);
T getContent() => content;
}
void main() {
var stringBox = Box<String>('Hello');
var intBox = Box<int>(42);
print(stringBox.getContent()); // Hello
print(intBox.getContent()); // 42
}T funge da variabile di tipo: quando crei Box<String>, ogni T nella classe diventa String. Questo ti offre la sicurezza dei tipi senza dover scrivere classi separate per ogni tipo.
Puoi usare più parametri di tipo quando la tua classe deve lavorare con più di un tipo:
class Pair<K, V> {
K first;
V second;
Pair(this.first, this.second);
}
void main() {
var pair = Pair<String, int>('age', 25);
print('${pair.first}: ${pair.second}'); // age: 25
}Le classi generiche sono alla base di un codice riutilizzabile e sicuro dal punto di vista dei tipi. Invece di duplicare la logica per tipi diversi o perdere informazioni sui tipi con dynamic, i generics ti permettono di scrivere codice flessibile che il compilatore può comunque verificare.
Sfida
FacileCostruiamo un sistema per incartare regali che usa classi generiche per creare contenitori flessibili per diversi tipi di oggetti. Creerai una classe generica Wrapper in grado di contenere qualsiasi tipo di contenuto e una classe GiftBox con due parametri di tipo per abbinare un regalo a un messaggio sul biglietto.
Organizzerai il codice in due file:
wrapper.dart: definisci qui le tue classi generiche:- Una classe generica
Wrapper<T>con una proprietàT contente un costruttore. Includi un metodounwrap()che restituisca il contenuto e un metododescribe()che stampiWrapped: [content] - Una classe generica
GiftBox<G, C>con due proprietà:G gifteC card. Includi un costruttore e un metodoopen()che stampiGift: [gift]su una riga eCard: [card]sulla riga successiva
- Una classe generica
main.dart: importa il tuo file wrapper e mostra le classi generiche con diversi tipi:- Crea un
Wrapper<String>che contenga'Chocolate'e chiamadescribe() - Crea un
Wrapper<int>che contenga42e chiamadescribe() - Crea un
Wrapper<double>che contenga3.14e chiamadescribe() - Stampa una riga vuota
- Crea un
GiftBox<String, String>con il regalo'Teddy Bear'e il biglietto'Happy Birthday!', poi chiamaopen() - Stampa una riga vuota
- Crea un
GiftBox<int, String>con il regalo100(che rappresenta l’importo di una carta regalo) e il biglietto'Congratulations!', poi chiamaopen()
- Crea un
Nota come la stessa classe Wrapper funzioni senza problemi con stringhe, numeri interi e numeri decimali. La classe GiftBox mostra come usare due parametri di tipo per abbinare tipi diversi: il regalo può essere di qualsiasi tipo, mentre il messaggio sul biglietto rimane una stringa.
Output previsto:
Wrapped: Chocolate
Wrapped: 42
Wrapped: 3.14
Gift: Teddy Bear
Card: Happy Birthday!
Gift: 100
Card: Congratulations!Provalo tu
import 'wrapper.dart';
void main() {
// TODO: Crea un Wrapper<String> contenente 'Chocolate' e chiama describe()
// TODO: Crea un Wrapper<int> contenente 42 e chiama describe()
// TODO: Crea un Wrapper<double> contenente 3.14 e chiama describe()
// TODO: Stampa una riga vuota
// TODO: Crea un GiftBox<String, String> con il regalo 'Teddy Bear'
// e il biglietto 'Happy Birthday!', poi chiama open()
// TODO: Stampa una riga vuota
// TODO: Crea un GiftBox<int, String> con il regalo 100
// e il biglietto 'Congratulations!', poi chiama open()
}
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