抽象類和接口是兩個很容易產生疑惑的概念,分不清它們的使用場景,其實只要記住兩點就比較好理解:
- 接口是對行為的抽象
- 抽象類是對子類有哪些屬性和行為的抽象
當你需要對一個類有哪些行為進行約束時,使用接口;需要為其他類提供一個模板以及一些通用的屬性和行為,使用抽象類。
在理解什么是抽象類和接口的前提下,延伸出一些思考:在一定程度上,接口似乎是比抽象類更底層的存在,是否可以理解為先有行為,對行為進行組合才能有類?
那么下面代碼中,抽象類對接口的實現有沒有實際意義?
<?phpinterface IAnimal
{public function move(): void;public function sleep(): void;public function eat(): void;
}interface Wag
{public function wag();
}interface Climb
{public function climb();
}abstract class AbstractAnimal implements IAnimal
{abstract function move(): void;public function sleep(): void{echo 'sleeping', PHP_EOL;}public function eat(): void{echo 'eating', PHP_EOL;}
}class Dog extends AbstractAnimal implements Wag
{function move(): void{echo 'dog running', PHP_EOL;}public function wag(): void{echo 'wagging', PHP_EOL;}
}class Cat extends AbstractAnimal implements Climb
{function move(): void{echo 'cat walking quietly', PHP_EOL;}public function climb(): void{echo 'climbing', PHP_EOL;}
}
如果更進一步,抽象類的方法和接口相同,并且都是抽象方法的情況下,接口和抽象類誰更有存在的意義?
抽象類是為了提高代碼復用,定義類之間的層次關系,接口是為了實現多態性和解耦。我們要知道兩者并不是對立關系,甚至目標一致,都是為了提高代碼質量。
工具是死的,但人是活的,所以我認為使用者并不用太過于糾結,代碼沒有百分百完美,也不是死板的教條。只要在需求和設計目標明確的前提下,選擇抽象類或接口,甚至組合起來使用都是可以的,解決實際問題才是我們最終的目的……
最后,再來回答一下前邊的三個問題:
- 抽象類和接口的層級關系:抽象類可以被視為介于接口和類之間的一種中間形式。
- 抽象類實現接口的意義:統一接口規范,確保抽象類和子類都遵循接口的約束。
- 全抽象方法的抽象類和接口誰更有意義:如果只是定義方法契約而不提供具體實現,接口更有意義;抽象類有明確擴展目標時,保留抽象類。