In PHP 7.2.0, partial contravariance was introduced by removing type restrictions on parameters in a child method. As of PHP 7.4.0, full covariance and contravariance support was added.
Covariance allows a child's method to return a more specific type than the return type of its parent's method. Whereas, contravariance allows a parameter type to be less specific in a child method, than that of its parent.
To illustrate how covariance works, a simple abstract parent class, Animal is created. Animal will be extended by children classes, Cat, and Dog.
<?php abstract class Animal { protected string $name; public function __construct(string $name) { $this->name = $name; } abstract public function speak(); } class Dog extends Animal { public function speak() { echo $this->name . " barks"; } } class Cat extends Animal { public function speak() { echo $this->name . " meows"; } }
Note that there aren't any methods which return values in this example. A few factories will be added which return a new object of class type Animal, Cat, or Dog.
<?php interface AnimalShelter { public function adopt(string $name): Animal; } class CatShelter implements AnimalShelter { public function adopt(string $name): Cat // instead of returning class type Animal, it can return class type Cat { return new Cat($name); } } class DogShelter implements AnimalShelter { public function adopt(string $name): Dog // instead of returning class type Animal, it can return class type Dog { return new Dog($name); } } $kitty = (new CatShelter)->adopt("Ricky"); $kitty->speak(); echo "\n"; $doggy = (new DogShelter)->adopt("Mavrick"); $doggy->speak();
The above example will output:
Continuing with the previous example with the classes Animal, Cat, and Dog, a class called Food and AnimalFood will be included, and a method eat(AnimalFood $food) is added to the Animal abstract class.
In order to see the behavior of contravariance, the eat method is overridden in the Dog class to allow any Food type object. The Cat class remains unchanged.
The next example will show the behavior of contravariance.
<?php $kitty = (new CatShelter)->adopt("Ricky"); $catFood = new AnimalFood(); $kitty->eat($catFood); echo "\n"; $doggy = (new DogShelter)->adopt("Mavrick"); $banana = new Food(); $doggy->eat($banana);
The above example will output:
But what happens if $kitty tries to eat the $banana?
The above example will output:
© 1997–2020 The PHP Documentation Group
Licensed under the Creative Commons Attribution License v3.0 or later.
https://www.php.net/manual/en/language.oop5.variance.php