Covariant-Schlüsselwort
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy. Lektion 61 von 110.
Wenn Sie eine Methode in einer Unterklasse überschreiben, erfordert Dart normalerweise, dass die Parametertypen exakt übereinstimmen. Aber manchmal möchten Sie, dass eine Methode einer Unterklasse einen spezifischeren Typ akzeptiert als die Elternklasse. Das Schlüsselwort covariant ermöglicht dies.
Stellen Sie sich ein Szenario vor, in dem eine Animal-Klasse eine Methode hat, die ein anderes Animal akzeptiert:
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');
}
}Ohne covariant würde Dart beanstanden, dass Dog nicht derselbe Typ wie Animal ist. Durch das Hinzufügen von covariant vor dem Parameter teilen Sie Dart mit: „Ich weiß, dass dies spezifischer ist, und ich werde sicherstellen, dass nur der richtige Typ übergeben wird.“
Dies ist nützlich, wenn Unterklassen logischerweise nur mit ihrer eigenen Art arbeiten sollten:
void main() {
Dog dog1 = Dog();
Dog dog2 = Dog();
dog1.chase(dog2); // Funktioniert: Hund jagt einen anderen Hund
}Aber Vorsicht – die Verwendung von covariant verschiebt die Typsicherheit zur Laufzeit. Wenn Sie die Methode über eine Referenz der Elternklasse mit dem falschen Typ aufrufen, erhalten Sie einen Laufzeitfehler anstelle eines Fehlers zur Kompilierzeit. Verwenden Sie es nur, wenn Sie sich bei den übergebenen Typen sicher sind.
Aufgabe
EinfachLass uns ein Haustier-Kompatibilitätssystem erstellen, das das Schlüsselwort covariant verwendet, um sicherzustellen, dass Haustiere nur mit ihrer eigenen Art spielen können. Du erstellst eine Hierarchie von Haustieren, in der jeder Typ über eine playWith-Methode verfügt, die nur ein Haustier desselben Typs akzeptiert.
Du organisierst deinen Code in zwei Dateien:
pets.dart: Definiere hier deine Haustierhierarchie:- Eine
Pet-Klasse mit einerString name-Eigenschaft und einem Konstruktor. Füge eine MethodeplayWith(Pet other)hinzu, die[name] plays with [other.name]ausgibt - Eine
Cat-Klasse, diePeterweitert undplayWithüberschreibt, wobei sie das Schlüsselwortcovariantverwendet, um nur eineCatzu akzeptieren. Sie sollte[name] and [other.name] chase yarn togetherausgeben - Eine
Dog-Klasse, diePeterweitert undplayWithüberschreibt, wobei sie das Schlüsselwortcovariantverwendet, um nur einenDogzu akzeptieren. Sie sollte[name] and [other.name] fetch the ball togetherausgeben - Eine
Rabbit-Klasse, diePeterweitert undplayWithüberschreibt, wobei sie das Schlüsselwortcovariantverwendet, um nur einRabbitzu akzeptieren. Sie sollte[name] and [other.name] hop around togetherausgeben
- Eine
main.dart: Importiere deine Haustierdatei und zeige, wie jeder Haustiertyp ausschließlich mit seiner eigenen Art spielt:- Erstelle zwei
Cat-Objekte mit den Namen'Whiskers'und'Mittens'und lasse anschließend Whiskers mit Mittens spielen - Erstelle zwei
Dog-Objekte mit den Namen'Buddy'und'Max'und lasse anschließend Buddy mit Max spielen - Erstelle zwei
Rabbit-Objekte mit den Namen'Flopsy'und'Cotton'und lasse anschließend Flopsy mit Cotton spielen
- Erstelle zwei
Das Schlüsselwort covariant ermöglicht es jeder Unterklasse, den Parametertyp von Pet auf ihren spezifischen Typ zu beschränken, wodurch typsichere Interaktionen zwischen Haustieren derselben Art gewährleistet werden.
Erwartete Ausgabe:
Whiskers and Mittens chase yarn together
Buddy and Max fetch the ball together
Flopsy and Cotton hop around togetherProbier es selbst
import 'pets.dart';
void main() {
// TODO: Erstelle zwei Cat-Objekte namens 'Whiskers' und 'Mittens'
// Dann lass Whiskers mit Mittens spielen
// TODO: Erstelle zwei Dog-Objekte namens 'Buddy' und 'Max'
// Dann lass Buddy mit Max spielen
// TODO: Erstelle zwei Rabbit-Objekte namens 'Flopsy' und 'Cotton'
// Dann lass Flopsy mit Cotton spielen
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienBibliotheken & ImportsEinführung in die OOPKlassen vs. ObjekteDas Schlüsselwort thisMethodenInstanzvariablenGrundlagen von KonstruktorenRückblick – Einfacher Taschenrechner4Null-Sicherheit
Einführung in die Null-SicherheitNullable vs. Non-NullableDie Operatoren ? und !Late-Schlüsselwort und Null-SicherheitNull-bewusste OperatorenNull-Sicherheit in KlassenRückblick – Benutzers профilsystem7Abstrakte Klassen & Interfaces
Abstrakte KlassenAbstrakte MethodenInterfaces in DartImplizite InterfacesImplementieren vs. ErweiternMehrere InterfacesZusammenfassung – Formrechner10Collections & Generics
Übersicht über List, Set und MapTypsichere CollectionsGenerische KlassenGenerische MethodenGenerische EinschränkungenIterable & IteratorRückblick – Generischer Speicher13Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungErweiterungsmethodenAufrufbare KlassenVersiegelte Klassen (Dart 3)Records (Dart 3)Muster & Matching (3.0)Enums mit Methoden16Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen2Konstruktoren in Dart
StandardkonstruktorBenannte KonstruktorenInitialisierungslistenKonstantenkonstruktorenFactory-KonstruktorenWeiterleitende KonstruktorenRückblick – Shape Builder5Kapselung
Öffentliche vs. private MemberDie _-Präfix-KonventionBibliotheksweite SichtbarkeitTiefergehende Getter & SetterInformationsverbergungRückblick – Studierendendaten8Mixins
Einführung in MixinsMixins erstellenMehrere Mixins verwendenDas Schlüsselwort „on“ in MixinsMixin vs. VererbungMixin vs. SchnittstelleRückblick – Tiersystem11Spezielle Methoden
toString()-ÜberschreibunghashCode- & ==-ÜberschreibungComparable-Schnittstellecall()-MethodenoSuchMethod-ÜberschreibungWiederholung – Benutzerdefinierte Collection14Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFabrikmusterBeobachtermusterStrategiemuster17Abschließende Herausforderungen
E-Learning-PlattformBankingsystemSpielcharaktersystemFahrzeugvermietung3Klassen-Eigenschaften
Instanz- vs. statische MemberFinal- und Const-FelderLate-VariablenStatische Methoden und FelderGetter und SetterRückblick – Bankkontoverwaltung6Vererbung
Grundlegende VererbungDas Schlüsselwort superMethodenüberschreibungDie Annotation @overrideDas Schlüsselwort final für KlassenKonstruktoren und VererbungZusammenfassung – Mitarbeiterhierarchie9Polymorphismus
Grundlagen des PolymorphismusPolymorphismus über InterfacesLaufzeit-TypüberprüfungDie Operatoren is & asCovariant-SchlüsselwortZusammenfassung – ZahlungsprozessorÜbe selbstständig: Online-Dart-Compiler