Menu
Coddy logo textTech

Mot-clé covariant

Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 61 sur 110.

Lorsque vous redéfinissez une méthode dans une sous-classe, Dart exige normalement que les types de paramètres correspondent exactement. Mais parfois, vous souhaitez qu'une méthode de sous-classe accepte un type plus spécifique que le parent. Le mot-clé covariant permet cela.

Considérez un scénario où une classe Animal possède une méthode qui accepte un autre 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');
  }
}

Sans covariant, Dart se plaindrait que Dog n'est pas du même type que Animal. En ajoutant covariant avant le paramètre, vous dites à Dart : « Je sais que c'est plus spécifique, et je m'assurerai que seul le bon type est transmis. »

Ceci est utile lorsque les sous-classes ne devraient logiquement fonctionner qu'avec leur propre type :

void main() {
  Dog dog1 = Dog();
  Dog dog2 = Dog();
  
  dog1.chase(dog2);  // Fonctionne : Un chien en poursuit un autre
}

Soyez toutefois prudent : l'utilisation de covariant déplace la sécurité de type au moment de l'exécution. Si vous appelez la méthode via une référence parente avec le mauvais type, vous obtiendrez une erreur d'exécution au lieu d'une erreur de compilation. Utilisez-le lorsque vous êtes certain des types transmis.

challenge icon

Défi

Facile

Construisons un système de compatibilité pour animaux de compagnie qui utilise le mot-clé covariant pour garantir que les animaux ne peuvent jouer qu'avec leurs semblables. Vous allez créer une hiérarchie d'animaux où chaque type possède une méthode playWith qui n'accepte que le même type d'animal.

Vous organiserez votre code en deux fichiers :

  • pets.dart : Définissez votre hiérarchie d'animaux ici :
    • Une classe Pet avec une propriété String name et un constructeur. Incluez une méthode playWith(Pet other) qui affiche [name] plays with [other.name]
    • Une classe Cat qui étend Pet et redéfinit playWith en utilisant le mot-clé covariant pour n'accepter qu'un Cat. Elle doit afficher [name] and [other.name] chase yarn together
    • Une classe Dog qui étend Pet et redéfinit playWith en utilisant le mot-clé covariant pour n'accepter qu'un Dog. Elle doit afficher [name] and [other.name] fetch the ball together
    • Une classe Rabbit qui étend Pet et redéfinit playWith en utilisant le mot-clé covariant pour n'accepter qu'un Rabbit. Elle doit afficher [name] and [other.name] hop around together
  • main.dart : Importez votre fichier d'animaux et démontrez comment chaque type d'animal joue exclusivement avec ses semblables :
    • Créez deux objets Cat nommés 'Whiskers' et 'Mittens', puis faites jouer Whiskers avec Mittens
    • Créez deux objets Dog nommés 'Buddy' et 'Max', puis faites jouer Buddy avec Max
    • Créez deux objets Rabbit nommés 'Flopsy' et 'Cotton', puis faites jouer Flopsy avec Cotton

Le mot-clé covariant permet à chaque sous-classe de restreindre le type de paramètre de Pet vers son type spécifique, garantissant des interactions de type sécurisé entre les animaux de la même espèce.

Sortie attendue :

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

Aide-mémoire

Le mot-clé covariant permet à une sous-classe de redéfinir une méthode avec un type de paramètre plus spécifique que celui de la classe parente.

Sans covariant, Dart exige que les types de paramètres correspondent exactement lors de la redéfinition des méthodes. Avec covariant, vous pouvez restreindre le type de paramètre dans la sous-classe :

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

C'est utile lorsque les sous-classes ne doivent travailler qu'avec leur propre type :

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

Important : L'utilisation de covariant déplace la sécurité de type de la compilation vers l'exécution. Si vous appelez la méthode via une référence parente avec le mauvais type, vous obtiendrez une erreur d'exécution au lieu d'une erreur de compilation.

Essayez vous-même

import 'pets.dart';

void main() {
  // TODO: Créer deux objets Cat nommés 'Whiskers' et 'Mittens'
  // Ensuite, faire en sorte que Whiskers joue avec Mittens
  
  
  // TODO: Créer deux objets Dog nommés 'Buddy' et 'Max'
  // Ensuite, faire en sorte que Buddy joue avec Max
  
  
  // TODO: Créer deux objets Rabbit nommés 'Flopsy' et 'Cotton'
  // Ensuite, faire en sorte que Flopsy joue avec Cotton
  
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet