Costruttori ed ereditarietà
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 41 di 110.
Quando una classe figlia estende una classe genitore, è necessario chiamare il costruttore della classe genitore per inizializzare correttamente i campi ereditati. Dart offre modi flessibili per gestire questa operazione tramite la lista di inizializzazione usando super.
Se la classe genitore ha un costruttore parametrizzato, la classe figlia deve richiamarlo esplicitamente:
class Person {
String name;
int age;
Person(this.name, this.age);
}
class Student extends Person {
String school;
Student(String name, int age, this.school) : super(name, age);
}Dart 2.17 ha introdotto i parametri super, una sintassi più pulita che inoltra i parametri direttamente al costruttore della classe genitore:
class Student extends Person {
String school;
// super.name e super.age vengono passati direttamente al costruttore di Person
Student(super.name, super.age, this.school);
}Quando lavori con i costruttori con nome, specifichi quale costruttore della classe genitore chiamare:
class Employee extends Person {
String department;
Employee(super.name, super.age, this.department);
Employee.intern(String name, this.department) : super(name, 18);
}La regola fondamentale è semplice: la classe genitore deve essere completamente inizializzata prima che la classe figlia aggiunga le proprie proprietà. Che tu usi la tradizionale chiamata super() o i super parametri più recenti, Dart garantisce che la catena di ereditarietà venga costruita correttamente dal genitore alla classe figlia.
Sfida
FacileCostruiamo un sistema di inventario dei prodotti che mostri come funzionano i costruttori con l’ereditarietà. Creerai una gerarchia in cui diversi tipi di prodotto estendono una classe di prodotto base, ciascuno richiedendo una corretta inizializzazione tramite i costruttori della classe genitore.
Organizzerai il codice in due file:
product.dart: definisci qui la gerarchia dei prodotti:- Una classe
Productcon le proprietàString nameedouble price, un costruttore che accetta entrambi i valori e un metodoinfo()che stampa[name]: $[price] - Una classe
Bookche estendeProducte aggiunge una proprietàString author. Usa i parametri super per inoltrarenameepriceal costruttore della classe genitore - Una classe
Electronicsche estendeProducte aggiunge una proprietàint warranty(in mesi). Usa la chiamata tradizionale asuper()nell’elenco di inizializzazione per passare i valori alla classe genitore
- Una classe
main.dart: importa il file dei prodotti e mostra entrambi gli approcci all’ereditarietà dei costruttori:- Crea un
Bookcon nome'Dart Essentials', prezzo29.99e autore'Jane Smith' - Chiama il suo metodo
info(), poi stampaAuthor: [author] - Stampa una riga vuota
- Crea un
Electronicscon nome'Wireless Mouse', prezzo45.50e garanzia24 - Chiama il suo metodo
info(), poi stampaWarranty: [warranty] months
- Crea un
Entrambe le classi figlie ereditano il metodo info() da Product senza doverlo sovrascrivere. La differenza principale sta nel modo in cui chiamano il costruttore della classe genitore: Book usa la sintassi più semplice dei parametri super, mentre Electronics usa l’approccio tradizionale con super() nell’elenco di inizializzazione.
Output previsto:
Dart Essentials: $29.99
Author: Jane Smith
Wireless Mouse: $45.5
Warranty: 24 monthsProvalo tu
import 'product.dart';
void main() {
// TODO: Crea un Book con:
// - name: 'Dart Essentials'
// - price: 29.99
// - author: 'Jane Smith'
// TODO: Chiama il metodo info() del libro
// TODO: Stampa "Author: [author]"
// TODO: Stampa una riga vuota
// TODO: Crea un Electronics con:
// - name: 'Wireless Mouse'
// - price: 45.50
// - warranty: 24
// TODO: Chiama il metodo info() dell'oggetto Electronics
// TODO: Stampa "Warranty: [warranty] months"
}
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