Menu
Coddy logo textTech

Das 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.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Haustier-Kompatibilitätssystem erstellen, das das Schlüsselwort covariant verwendet, um sicherzustellen, dass Haustiere nur mit ihrer eigenen Art spielen können. Sie werden eine Hierarchie von Haustieren erstellen, bei der jeder Typ eine playWith-Methode hat, die nur denselben Haustiertyp akzeptiert.

Sie werden Ihren Code in zwei Dateien organisieren:

  • pets.dart: Definieren Sie hier Ihre Haustierhierarchie:
    • Eine Pet-Klasse mit einer String name-Eigenschaft und einem Konstruktor. Fügen Sie eine Methode playWith(Pet other) hinzu, die [name] plays with [other.name] ausgibt.
    • Eine Cat-Klasse, die Pet erweitert und playWith unter Verwendung des Schlüsselworts covariant überschreibt, um nur eine Cat zu akzeptieren. Sie sollte [name] and [other.name] chase yarn together ausgeben.
    • Eine Dog-Klasse, die Pet erweitert und playWith unter Verwendung des Schlüsselworts covariant überschreibt, um nur einen Dog zu akzeptieren. Sie sollte [name] and [other.name] fetch the ball together ausgeben.
    • Eine Rabbit-Klasse, die Pet erweitert und playWith unter Verwendung des Schlüsselworts covariant überschreibt, um nur ein Rabbit zu akzeptieren. Sie sollte [name] and [other.name] hop around together ausgeben.
  • main.dart: Importieren Sie Ihre Haustier-Datei und demonstrieren Sie, wie jeder Haustiertyp exklusiv mit seiner eigenen Art spielt:
    • Erstellen Sie zwei Cat-Objekte namens 'Whiskers' und 'Mittens', und lassen Sie Whiskers mit Mittens spielen.
    • Erstellen Sie zwei Dog-Objekte namens 'Buddy' und 'Max', und lassen Sie Buddy mit Max spielen.
    • Erstellen Sie zwei Rabbit-Objekte namens 'Flopsy' und 'Cotton', und lassen Sie Flopsy mit Cotton spielen.

Das Schlüsselwort covariant ermöglicht es jeder Unterklasse, den Parametertyp von Pet auf ihren spezifischen Typ einzugrenzen, was typsichere Interaktionen zwischen Haustieren derselben Art gewährleistet.

Erwartete Ausgabe:

Whiskers and Mittens chase yarn together
Buddy and Max fetch the ball together
Flopsy and Cotton hop around together

Spickzettel

Das Schlüsselwort covariant ermöglicht es einer Unterklasse, eine Methode mit einem spezifischeren Parametertyp zu überschreiben als die Elternklasse.

Ohne covariant verlangt Dart, dass die Parametertypen beim Überschreiben von Methoden exakt übereinstimmen. Mit covariant können Sie den Parametertyp in der Unterklasse einschränken:

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');
  }
}

Dies ist nützlich, wenn Unterklassen nur mit ihrem eigenen Typ arbeiten sollen:

void main() {
  Dog dog1 = Dog();
  Dog dog2 = Dog();
  
  dog1.chase(dog2);  // Funktioniert: Dog chasing another dog
}

Wichtig: Die Verwendung von covariant verschiebt die Typsicherheit von der Kompilierzeit 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.

Probier 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
  
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung