子類別、父類別,互相替代的問題。
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
協變與逆變 - 維基百科,自由的百科全書
沒有留言:
張貼留言