What is covariant in Dart
What is the article about?
The covariant keyword was introduced into Dart to combat the important problem of method overriding.
The article contains an analysis of the problem, a description of how covariant works, and an example of its use to solve the problem.
Problem
If a method of a parent class is overridden in a child class, then the parameter of the child class method can be an instance only of the class that is specified in this parameter in the method of the parent class.
Thus, if in an overridden method you use a parameter of a class that is a child of the class that is specified for the parameter in the method of the inherited class, an error will occur. An example is shown in Fig. 1.
Cat is a subclass of Animal that overrides the eat method. Animal in the eat method requires a Food data type parameter.
Fish is a subclass of Food – i.e. implicitly, instances of the class Fish are instances of the class Food. However, if you specify a parameter with the data type Fish in Cat.eat, an error will occur.
The situation is similar with the implementation of the interface (see Fig. 2).
To solve this problem, Dart 2.12 introduced the covariant keyword.
What is covariant
covariant is a keyword that is used in conjunction with method parameters when child classes override methods of parent classes in order to solve the problem of child classes not being recognized when methods are overridden.
A parameter to a child method, instead of using the data type specified in the overridden parent class method, can use a data type that is a child of the parent class specified in the method. An example is shown in Fig. 3.
The covariant keyword tells the parser not to perform strict data type checking. However, if you use a data type for a parameter that is not a child class of the class specified for the parameter in a method of the parent class, an error will occur (see Figure 4).
The covariant keyword can be used in a superclass method or in a derived class method. However, it is good practice to use covariant in parent class methods to explicitly indicate in the parent class interface that child classes can change this interface. This approach also allows all child classes in a method override to change the data type for a parameter defined with covariant. An example is shown in Fig. 5.
Conclusion
The covariant keyword is useful to know, because something similar to the example presented in the article can very well occur in real life. Covariant is also often used in Flutter sources and is often asked during interviews.
Thank you for your attention!
Code from examples
class Food {}
class Animal {
void eat(covariant Food food) {
print('Animal eats $food');
}
}
class Fish extends Food {}
class Cat extends Animal {
@override
void eat(Fish food) {
print('Cat eats $food');
}
}
class Meat extends Food {}
class Dog extends Animal {
@override
void eat(Meat food) {
print('Dog eats $food');
}
}
void main() {
Food food = Food();
Animal animal = Animal();
animal.eat(food);
Fish fish = Fish();
Cat cat = Cat();
cat.eat(fish);
Meat meat = Meat();
Dog dog = Dog();
dog.eat(meat);
}