Parola chiave covariant
Fa parte della sezione Programmazione orientata agli oggetti del percorso Dart di Coddy. Lezione 61 di 110.
Quando esegui l'override di un metodo in una sottoclasse, Dart normalmente richiede che i tipi dei parametri corrispondano esattamente. Ma a volte vuoi che un metodo della sottoclasse accetti un tipo più specifico di quello della classe padre. La parola chiave covariant lo consente.
Considera uno scenario in cui una classe Animal ha un metodo che accetta un altro Animal:
class Animal {
void chase(Animal other) {
print('Chasing an animal');
}
}
class Dog extends Animal {
@override
void chase(covariant Dog other) {
print('Dog chasing another dog');
}
}Senza covariant, Dart si lamenterebbe perché Dog non è dello stesso tipo di Animal. Aggiungendo covariant prima del parametro, dici a Dart: "So che questo è più specifico e mi assicurerò che venga passato solo il tipo corretto."
È utile quando le sottoclassi dovrebbero logicamente funzionare solo con esemplari del proprio tipo:
void main() {
Dog dog1 = Dog();
Dog dog2 = Dog();
dog1.chase(dog2); // Funziona: Dog insegue un altro cane
}Fai attenzione, però: usare covariant sposta la sicurezza dei tipi in fase di esecuzione. Se chiami il metodo tramite un riferimento al genitore con il tipo sbagliato, otterrai un errore in fase di esecuzione invece che un errore in fase di compilazione. Usalo quando sei sicuro dei tipi passati.
Sfida
FacileCostruiamo un sistema di compatibilità tra animali domestici che usa la parola chiave covariant per assicurarsi che gli animali possano giocare solo con i propri simili. Creerai una gerarchia di animali domestici in cui ogni tipo ha un metodo playWith che accetta solo animali dello stesso tipo.
Organizzerai il codice in due file:
pets.dart: definisci qui la gerarchia degli animali domestici:- Una classe
Petcon una proprietàString namee un costruttore. Includi un metodoplayWith(Pet other)che stampa[name] plays with [other.name] - Una classe
Catche estendePete sovrascriveplayWithusando la parola chiavecovariantper accettare solo unCat. Dovrebbe stampare[name] and [other.name] chase yarn together - Una classe
Dogche estendePete sovrascriveplayWithusando la parola chiavecovariantper accettare solo unDog. Dovrebbe stampare[name] and [other.name] fetch the ball together - Una classe
Rabbitche estendePete sovrascriveplayWithusando la parola chiavecovariantper accettare solo unRabbit. Dovrebbe stampare[name] and [other.name] hop around together
- Una classe
main.dart: importa il file degli animali domestici e mostra come ogni tipo di animale giochi esclusivamente con i propri simili:- Crea due oggetti
Catchiamati'Whiskers'e'Mittens', poi fai giocare Whiskers con Mittens - Crea due oggetti
Dogchiamati'Buddy'e'Max', poi fai giocare Buddy con Max - Crea due oggetti
Rabbitchiamati'Flopsy'e'Cotton', poi fai giocare Flopsy con Cotton
- Crea due oggetti
La parola chiave covariant permette a ogni sottoclasse di restringere il tipo del parametro da Pet al proprio tipo specifico, garantendo interazioni sicure dal punto di vista dei tipi tra animali domestici della stessa specie.
Output previsto:
Whiskers and Mittens chase yarn together
Buddy and Max fetch the ball together
Flopsy and Cotton hop around togetherProvalo tu
import 'pets.dart';
void main() {
// TODO: Crea due oggetti Cat chiamati 'Whiskers' e 'Mittens'
// Poi fai giocare Whiskers con Mittens
// TODO: Crea due oggetti Dog chiamati 'Buddy' e 'Max'
// Poi fai giocare Buddy con Max
// TODO: Crea due oggetti Rabbit chiamati 'Flopsy' e 'Cotton'
// Poi fai giocare Flopsy con Cotton
}
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