雖然接觸面向?qū)ο笳Z言很長時間了,可是要是說對面向?qū)ο蟮乃枷胗卸嗝瓷羁痰牧私馓竿穑瑓s也未必次哈。所以開始整理知識,寫一點對面向?qū)ο蟮睦斫庑缘臇|西吆录,算是一種總結(jié)類的日志吧窑滞。畢竟對面向?qū)ο蟮闹R了解的很淺薄,難免有理解有誤的地方恢筝,如若您發(fā)現(xiàn)哀卫,請務(wù)必指出,希望我們共同進步撬槽。
抽象類
首先來介紹一下抽象類是什么此改。可以簡單的理解:被abstract
修飾的方法叫做抽象方法侄柔,而一個類如果擁有抽象方法共啃,那么它就是抽象類,且也必須用abstract
修飾暂题。
百度百科中這么說抽象類:
抽象類往往用來表征對問題領(lǐng)域進行分析勋磕、設(shè)計中得出的抽象概念,是對一系列看上去不同敢靡,但是本質(zhì)上相同的具體概念的抽象
可以得知抽象類是本質(zhì)相同的具體概念的抽象(簡單點挂滓,抽象類是對類的抽象),抽象是什么啸胧,就是不能實現(xiàn)的赶站,所以抽象類不能夠被實例化。不能實例化的類用來干什么纺念?答案是作為基類使用贝椿。
一個抽象類被繼承,由于抽象類的特性陷谱,我們可以得到任意個不同的實現(xiàn)方式烙博,帶來各種不同的效果瑟蜈,既嚴謹又靈活。
按照慣例我們列舉一下一個抽象類所具有的特性:
- 如果一個類中存在一個及以上方法被聲明為抽象的渣窜,那么該類必須也是抽象的铺根;反之不正確(一個類是抽象類,那么該類中必然存在一個及以上方法為抽象方法)乔宿;
- 抽象類不能被實例化位迂;
- 抽象方法必須是抽象的(即不能實現(xiàn)具體內(nèi)容),并以結(jié)束符結(jié)尾详瑞;
- 抽象類允許存在非抽象方法掂林;
- 繼承抽象類的子類必須實現(xiàn)抽象類中的抽象方法,除非該子類也是抽象類坝橡;
- 子類繼承泻帮,實現(xiàn)的抽象方法不能改變其參數(shù)(數(shù)量/類型);
- 子類繼承,其實現(xiàn)的抽象方法訪問控制只能更加寬松,而不能更加嚴格蹦魔;
- 抽象方法訪問控制條件不能為
private
缠局,因為被聲明為私有的方法不能被子類繼承。
由上述,你可能模模糊糊知道抽象類是用來做什么的。我再通過一個例子來說明:
某日,你老板要求團隊開發(fā)一個數(shù)據(jù)庫操作類柒竞,必須包括且不限于MySQL,SQLserver播聪,oracle等朽基。老板說話了,趕緊弄啊离陶。很快稼虎,弄好了,代碼寫的也很優(yōu)雅招刨,執(zhí)行效率也不錯霎俩,但是老板很生氣,因為沒法用啊沉眶,幾個數(shù)據(jù)庫類中方法完全不一樣打却,一個查詢方法,有定義成select的谎倔,有定義成getData的柳击,亂七八糟。
怎么解決這種問題片习。當(dāng)然可以事先溝通好捌肴,但是如果使用了抽象類就能完全的解決問題蹬叭。定義一個數(shù)據(jù)庫抽象類,在其中定義必要使用的抽象方法状知,要求各個數(shù)據(jù)庫操作類必須繼承自該抽象類秽五,OK,問題解決试幽。
如下:
abstract class db {
# 連接方法
protected abstract function connect();
# 執(zhí)行查詢語句
public abstract function query($sql);
# 添加操作
public abstract function insert($sql);
# 刪除操作
public abstract function delete($sql);
# 更新操作
public abstract function update($sql);
# 查詢操作
public abstract function select($sql);
}
接口
類是對一組具有共同特征的事物的抽象描述(對現(xiàn)實的抽象)筝蚕,而對不同類中本質(zhì)相同的概念的抽象是抽象類(類的抽象)卦碾。如果說還存在比抽象類更為抽象的铺坞,那就是說 接口 了。接口是一系列抽象方法的集合洲胖。
為什么說接口比抽象類更加抽象呢济榨。因為接口中只能存在聲明為abstract
的公共方法,而不能有普通方法绿映。如下:
interface demo {
public abstract show();
}
而擒滑,這樣是錯誤的
interface demo {
public abstract function show();
protected abstract function display();
public function say() {
echo 'Hello';
}
}
說了不少,到底接口是啥呢叉弦?看了一篇文章丐一,上面這么說接口:
接口類說白了,就是一個類的模板淹冰,一個類的規(guī)定库车,如果你屬于這類,你就必須遵循我的規(guī)定樱拴,少一個都不行柠衍,但是具體你怎么去做,我不管晶乔,那是你的事
接口類 說的太不嚴謹了珍坊,應(yīng)該添加引號,需要知道接口并不是類正罢。不過說接口是模板比較正確阵漏。
而另一篇文章所說的我比較認同,接口是對行為的抽象翻具。什么叫行為的抽象履怯?
那先要說說行為。類是對現(xiàn)實的抽象嘛呛占,所以用現(xiàn)實來舉個例子虑乖。
人的說話是不是天生的?自然不是晾虑,如果天生會說話疹味,那一般出現(xiàn)在重生小說里面仅叫。說話需要通過后天學(xué)習(xí),如果不學(xué)習(xí)(例如新聞中被狼收養(yǎng)的孩子)就不會說話(狼孩只會狼嚎)糙捺。在這里诫咱,說話就是一種行為,是通過學(xué)習(xí)洪灯,通過思想支配表現(xiàn)出來的坎缭。可以說签钩,說(人)話就是一個接口掏呼,正常人實現(xiàn)了該接口,所以能夠說話铅檩,而狼孩實現(xiàn)的是狼嚎接口憎夷,所以他會狼嚎,而不會說話昧旨。
這個例子的結(jié)論是拾给,行為是人非天生的(不能直接繼承的),需要通過后天學(xué)習(xí)(繼承接口)的外在活動兔沃。
通過對行為的抽象蒋得,體現(xiàn)在面向?qū)ο笳Z言中,那就是接口乒疏,它是不適合在類中直接體現(xiàn)(或用來描述類)(類又可能需要)的方法的集合额衙。
理論結(jié)合實踐,反應(yīng)在實際編程中缰雇,又如何運用接口入偷?慚愧的很,我開發(fā)PHP程序可以說沒有運用到過接口械哟。而我見到的運用接口的實例都是通過多態(tài)來體現(xiàn)的疏之。
如《深入PHP面向?qū)ο蟆⒛J脚c實踐》書中所舉的例子暇咆,有一個接口Chargeable
锋爪,規(guī)定了抽象方法getPrice
,被ShopProduct
所繼承實現(xiàn)爸业,而CdProduct
繼承自ShopProduct
其骄。由于實現(xiàn)接口的類繼承接受了它繼承的類與所實現(xiàn)的接口的類型,所以CdProduct
同時屬于CdProduct
扯旷、ShopProduct
拯爽、Chargeable
。
所以在客戶端代碼中可以定義方法cdInfo
來限制僅獲取來自CdProduct
的內(nèi)容:
// ……
public function cdInfo(CdProduct $item) {
// ……
}
可以定義addProduct
來限制僅允許商品進入:
// ……
public function addProduct(ShopProduct $item) {
// cd钧忽、book等商品能夠被添加 而user不能進入
// ……
}
當(dāng)我們只關(guān)注于計價的時候就可以定義定義addChargeable
來確保傳遞的對象存在計價方法:
// ……
public function addChargeable(Chargeable $item) {
// ……
}
好了毯炮,對抽象類與接口本次就寫到這里逼肯,等過一段時間再來做新的總結(jié),可能會有新的收獲桃煎。由于本人才疏學(xué)淺篮幢,理解或解釋不當(dāng)?shù)牡胤剑垊?wù)必指出为迈,不勝感激三椿。