抽象類和抽象方法和介面
有些知識,是為了解決某個場景中的難題而生。 瞭解那個"令人尷尬"的場景,為了解知識點更重要。
假設如下場景: 團隊準備開發某王站,表建好了,頁面設計好了。
A組負責開發底層資料庫類(DB),上傳類。 B級負責呼叫DB類
A組發生了爭執,MySQL? Oracle? DB2? sqlite?
B組.... 漫長等待.
當確定用mysql的時候,B組已經等了一個月了。
能否讓B組不等待?
解決: A組和B組先定1個數據庫類的模板: 模板中對:方法名,引數,返回值,都做嚴格的規定 此時,不
管A組選用什麼資料庫,對於B組來說,沒有任何影響;
1 abstract class aDB{ 2 /** 3 * 引數:sql語句4 * 返回型別:array 5 **/ 6 abstract public function getAll($sql); 7 abstract public function getRow($sql); 8 } 9 10 class Mysql extends aDB{ 11 public function getAll($sql){ 12 13 } 14 public function getRow($sql){ 15 16 } 17 }
在程式設計中,有個概念叫"面向介面程式設計"。
開發和呼叫者之間,不直接通訊,大家都對"共同的標準"負責。
比如:B組呼叫以aDb為準,A組最終的開發,也依aDb為準。
生活中的例子:
抽象類和方法的特徵:
1、類前要加abstract,則為抽象類。
2、方法前也可以加abstract,則為抽象方法。
3、抽象方法沒有方法體
4、抽象類中也可以有已經實現的方法。但,只有要1個方法為抽象,則類仍是抽象的。
5、抽象類不能例項化
6、抽象類必須被繼承,實現所有的抽象方法才能使用。
1 <?php 2 //多個物件協同⼯作 3 //飼養員與不同動物表演 4 5 //飼養員 6 class Person{ 7 public $name; 8 public function __construct($name){ 9 $this->name = $name; 10 } 11 public function work($obj){ 12 echo $this->name.'正在工作<br/>'; 13 //1.餵養動物 14 15 $obj->eat(); 16 //2.表演 17 $obj->show(); 18 } 19 } 20 //父類裡面的方法只是用於保證子類裡面有這個方法 21 abstract class Animal{ 22 public function eat(){ 23 echo '正在吃東西...<br/>'; 24 } 25 26 //抽象方法(半成品) 27 abstract public function show(); 28 } 29 //二狗 30 class Dog extends Animal{ 31 public function eat(){ 32 echo '狗吃吃吃。。。。<br/>'; 33 } 34 public function show(){ 35 echo '玩球球。。。。<br/>'; 36 } 37 } 38 //小貓 39 class Cat extends Animal{ 40 public function eat(){ 41 echo '吃大雨...<br/>'; 42 } 43 public function show(){ 44 echo '補充耗。。。<br/>'; 45 } 46 } 47 //猴子 48 class Monkey extends Animal { 49 public function eat(){ 50 echo '吃香蕉。。。<br/>'; 51 } 52 public function play(){ 53 echo '玩個蕉...<br/>'; 54 } 55 public function show(){ 56 echo '玩個頭...<br/>'; 57 } 58 } 59 60 //例項化物件 61 $lq = new Person('老王'); 62 $wc = new Dog; 63 $tom = new Cat; 64 $wk = new Monkey; 65 //飼養員在公作 66 //$lq->work($wc); 67 //$lq->work($tom); 68 $lq->work($wk);
總結:
1 <?php 2 abstract class A{ 3 abstract public function eat(); 4 abstract public function say(); 5 } 6 //抽象類必須繼承 而且還要完成裡面的所有抽象方法 7 abstract class B extends A{ 8 //抽象方法必須被重寫 9 public function say(){ 10 } 11 public function eat(){ 12 } 13 //繼承的時候還可以追加抽象方法 14 abstract public function he(); 15 } 16 //重寫了所有抽象方法的類才算是一個完整的類 才能被例項化 17 class C extends B{ 18 public function he(){ 19 } 20 } 21 $a = new C; 22 var_dump($a);
介面
抽象類可以理解為"類的模板",介面則是"方法"的模板。 即,接⼝的粒度更小,用於描述通用的方
法。
/* 比如一個社交網站, 關於使用者的處理是核心應用. 登陸 退出 寫信 看信 招呼 更換⼼情 吃飯 罵人 搗亂 示愛 撩騷 這麼多的方法,都是使用者的方法, 自然可以寫一個user類,全包裝起來 但是,分析使用者一次性使不了這麼方法 使用者資訊類:{登陸,寫信,看信,招呼,更換心情,退出} 使用者娛樂類:{登陸,罵人,搗亂,示愛,撩騷,退出} 開發網站前,分析出來這麼多方法, 但是,不能都裝在一個類裡, 分成了2個類,甚至更多. 作用應用邏輯的開發,這麼多的類,這麼多的方法,都暈了. */ interface UserBase { public function login($u,$p); public function logout(); } interface UserMsg { public function wirteMsg($to,$title,$content); public function readMsg($from,$title); } interface UserFun { public function spit($to); public function showLove($to); } /* 作為呼叫者, 我不需要了解你的使用者資訊類,使用者娛樂類, 我就可以知道如何呼叫這兩個類 因為: 這兩個類 都要實現 上述介面. 通過這個介面,就可以規範開發. */ /* 下面這個類,和介面宣告的引數不一樣,就報錯, 這樣,介面強制統一了類的功能 不管你有幾個類,一個類中有幾個方法
我只知道,方法都是實現的介面的方法. */ class User implements UserBase { public function login($u) { } } interface USB{ //在接口裡面所有的方法都是抽象方法 所以不需要額外的修飾 public function run(); } interface typeC{ public function xxx(); } //介面與介面之間是繼承關係 interface PS2 extends USB{ public function move(); } class A{} //類與介面之間是實現關係 //實現介面可以多實現 中間使用逗號隔開 //類在繼承其他類的同時可以實現介面(多時間) 繼承一定要在實現前面 class Mouse extends A implements PS2,typeC{ public function run(){} public function move(){} public function xxx(){} }
介面特徵:
1、在接口裡面所有的方法都是抽象方法 不需要額外修飾
2、接口裡面不能寫成員屬性裡面只能有常量和抽象方法
3、介面與介面之間是繼承關係
4、類與介面之間是實現關係
5、實現介面可以多實現 中間使⽤逗號隔開
6、類在繼承其他類的同時可以實現介面(多實現),繼承一定要在實現前面
抽象類與介面的區別
抽象類:主要用於雙方協作的規範,屬於大方向模版。
介面:組成事務具體零件的規範,屬於具體開發模版。
如何選擇?
如果你僅僅是用於指定這個模組要不要開發,是現在開發還是以後開發,起一個指引作用,要使用接
口。
如果你在制定大規範,並且涉及各部門之間的配合,要使用抽象類