子類別、父類別,互相替代的問題。
Covariance(協變):原本規定是父類,但用子類取代。如果類別設計符合里氏替換原則(子類別必須能替換父類別),這通常是被允許的。
Contravariance(逆變):原本規定是子類,但用父類取代。
範例:
範例:
//一個食物類別
class Food {
}
//動物食物(食物類別的子類)
class AnimalFood extends Food {
}
//一個動物類別,有一個吃食物的方法
class Animal {
public function eat(AnimalFood $ff) {//規定只能吃"動物食物"
echo get_class($this) . " 吃 " . get_class($ff);
}
}
//有一個動物收容所介面,有一個領養動物的方法,想開動物收容所,須實現此方法
interface AnimalShelter {
public function adoption(): Animal; //規定只能領養動物類別
}#Covariance(協變):
//1.有一個人,想要開狗收容所,所以要實現狗領養的方法
//2.收容所介面,規定只能領養 Animal 類別,但可用 Dog 子類別取代
// 原本規定是父類 Animal,但用子類 Dog 取代=>協變
class Dog extends Animal {//收容所要有狗,建立 Dog 類別
}
//狗收容所
class DogShelter implements AnimalShelter {
//規定只能領養Animal類別,但可用Dog子類別取代(協變)
public function adoption(): Dog {//返回值協變
return new Dog();
}
}
//一個狗收容所
$ds = new DogShelter();
//從狗收容所領養了一隻動物
$aa = $ds->adoption();
//看看從狗收容所領養了什麼動物
echo "領養了:" . get_class($aa); //領養了:Dog
//這是狗,能吃AnimalFood,餵牠吃
$aa->eat(new AnimalFood()); //Dog 吃 AnimalFood
//但不能吃 Food (全部的食物)
//Fatal error: Uncaught TypeError: Animal::eat(): Argument #1 ($ff) must be of type AnimalFood, Food given
//$aa->eat(new Food());#Contravariance(逆變):
//有一個人,想要開豬收容所,所以要實現豬領養的方法
//1.收容所要有豬,所以建立 Pig 類別,
//2.建立 Pig 類別時,才想到豬不只可吃動物食物 class AnimalFood,而是所有食物 class Food 都可以吃
// 但動物類別 class Animal 裡的 eat(AnimalFood $ff) 方法,已經限制只能吃動物食物 class AnimalFood
//3.所以只好將豬的 eat(AnimalFood $ff) 覆寫,改成 eat(Food $ff)
// 原本規定是子類 AnimalFood,但用父類 Food 取代=>逆變
class Pig extends Animal {
//規定用AnimalFood,但覆寫後,改用Food父類取代(逆變)
public function eat(Food $ff) {//方法參數逆變
echo get_class($this) . " 吃 " . get_class($ff);
}
}
//豬收容所
class PigShelter implements AnimalShelter {
public function adoption(): Pig {
return new Pig();
}
}
//一個豬收容所
$ds = new PigShelter();
//從豬收容所領養了一隻動物
$aa = $ds->adoption();
//看看從豬收容所領養了什麼動物
echo "領養了:" . get_class($aa); //領養了:Pig
//這是豬,什麼都能吃,AnimalFood、Food 都餵牠吃
$aa->eat(new AnimalFood()); //Pig 吃 AnimalFood
$aa->eat(new Food()); //Pig 吃 Food參考:
- https://www.php.net/manual/zh/language.oop5.variance.php
PHP: 协变与逆变 - Manual - https://zh.wikipedia.org/zh-tw/%E5%8D%8F%E5%8F%98%E4%B8%8E%E9%80%86%E5%8F%98
協變與逆變 - 維基百科,自由的百科全書
沒有留言:
張貼留言