Коваріантність та контраваріантність

У PHP 7.2.0 було додано часткову контраваріантність шляхом усунення обмежень типу для параметрів у дочірньому методі. Починаючи з PHP 7.4.0, додано повну підтримку коваріантності та контраваріантності.

Коваріантність дозволяє дочірньому методу повертати більш конкретний тип, ніж тип значення його батьківського методу, що повертається. У той час як контраваріантність дозволяє типу параметра в дочірньому методі бути менш специфічним, ніж у батьківському.

Оголошення типу вважається більш конкретним у наступному випадку:

В іншому випадку клас типу вважається менш конкретним.

Коваріантність

Щоб проілюструвати, як працює підступність, створимо простий абстрактний батьківський клас Animal. Animal буде розширено за рахунок дочірніх класів Cat та Dog.

Loading...

Зверніть увагу, що на прикладі немає методів, які повертають значення. Буде додано декілька фабрик, які повертають новий об'єкт типу класу Animal, Cat або Dog.

Loading...

Результат виконання наведеного прикладу:

Рыжик мяукает
Бобик лает

Контраваріантність

Продовжуючи попередній приклад, де ми використовували класи Animal, Cat і Dog, ми введемо нові класи Food і AnimalFood і додамо в абстрактний клас Animal новий метод eat(AnimalFood $food).

Loading...

Щоб побачити суть контраваріантності, ми перевизначимо метод eat класу Dog таким чином, щоб він міг приймати будь-який об'єкт класу Food. Клас Cat залишимо без змін.

Loading...

Наступний приклад покаже поведінку контраваріантності.

Loading...

Результат виконання наведеного прикладу:

Рыжик ест AnimalFood
Бобик ест Food

Але що станеться, якщо $kitty спробує з'їсти (eat()) банан ($ banana)?

Loading...

Результат виконання наведеного прикладу:

Loading...