這篇文章主要介紹“怎么理解PHP7.2忽略父類(lèi)方法以及Liskov替換原則相關(guān)問(wèn)題”,在日常操作中,相信很多人在怎么理解PHP7.2忽略父類(lèi)方法以及Liskov替換原則相關(guān)問(wèn)題問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”怎么理解PHP7.2忽略父類(lèi)方法以及Liskov替換原則相關(guān)問(wèn)題”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
創(chuàng)新互聯(lián)公司專(zhuān)注于成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站制作、網(wǎng)站開(kāi)發(fā)。公司秉持“客戶至上,用心服務(wù)”的宗旨,從客戶的利益和觀點(diǎn)出發(fā),讓客戶在網(wǎng)絡(luò)營(yíng)銷(xiāo)中找到自己的駐足之地。尊重和關(guān)懷每一位客戶,用嚴(yán)謹(jǐn)?shù)膽B(tài)度對(duì)待客戶,用專(zhuān)業(yè)的服務(wù)創(chuàng)造價(jià)值,成為客戶值得信賴的朋友,為客戶解除后顧之憂。
細(xì)說(shuō) PHP 7.2 子類(lèi)覆蓋方法省略參數(shù)類(lèi)型功能以及 Liskov 替換原則
PHP 7.2 出來(lái)也有段時(shí)間了,關(guān)于新版本有什么新改進(jìn),只要你關(guān)心 PHP 的發(fā)展,應(yīng)該都看過(guò)。這里只細(xì)說(shuō)一個(gè)可能會(huì)有誤解的新功能。
PHP 7.2 可以在當(dāng)子類(lèi)覆蓋(override)父類(lèi)方法的時(shí)候,忽略父類(lèi)方法的定義的參數(shù)的類(lèi)型(type hint):
class Foo { public function bar(SomeClass $obj) {} } class Foobar extends Foo { public function bar($obj) {} // 這在 PHP7.2 版本之前是會(huì)報(bào)錯(cuò)的 }
我看有些網(wǎng)站介紹此功能的時(shí)候,說(shuō)其目的是為了『方便重構(gòu)。如果以后父類(lèi)方法的參數(shù)類(lèi)型變了,子類(lèi)不用再全部換一遍』。聽(tīng)起來(lái)好像很有道理。按這說(shuō)法,隱含的意思是:如果子類(lèi)忽略了父類(lèi)方法參數(shù)類(lèi)型,被調(diào)用時(shí)還是會(huì)檢查參數(shù)類(lèi)型。實(shí)際情況是不是這樣做一下實(shí)驗(yàn)就知道了:
setFoo('I am a string!');
如果上面的說(shuō)法是對(duì)的,setFoo 接受字符串參數(shù)的時(shí)候就應(yīng)該報(bào)錯(cuò),然而上面代碼在 7.2 下并沒(méi)有任何報(bào)錯(cuò)信息,但如果子類(lèi)的 setFoo 方法加上了參數(shù)類(lèi)型,就會(huì)立馬報(bào)錯(cuò)了。記住網(wǎng)上很多說(shuō)法都不可信,除了我這個(gè)小站……
上面的實(shí)驗(yàn)說(shuō)明子類(lèi)方法可省略參數(shù)類(lèi)型,其目的肯定不是為了方便重構(gòu)。那真正目的是什么呢?
在 PHP 7.1 里有一個(gè)新功能,是『可設(shè)置方法或函數(shù)的參數(shù)和返回類(lèi)型是否可以為 null』。其中有一條看上去比較別扭的規(guī)則:『子類(lèi)方法參數(shù)類(lèi)型范圍放寬(即父類(lèi)參數(shù)若不能為 null ,子類(lèi)參數(shù)可支持 null),但返回類(lèi)型縮緊(父類(lèi)若不能返回 null,子類(lèi)必須也不行;若父類(lèi)可以返回 null,子類(lèi)可以不返回 null)』,當(dāng)時(shí)我很簡(jiǎn)單說(shuō)了一句,是因?yàn)?『Liskov 替換原則』,但沒(méi)有做深入介紹。身邊的 PHPer 們關(guān)注 OOP 原則的不多,但我認(rèn)為它應(yīng)該被每個(gè)工程師知道,還是介紹一下。
Liskov 替換原則簡(jiǎn)單一句話:父類(lèi)出現(xiàn)的地方,替換成子類(lèi)也能運(yùn)行,即子類(lèi)可無(wú)腦替換父類(lèi)。其實(shí)從語(yǔ)言設(shè)計(jì)來(lái)說(shuō),我認(rèn)為此原則就是對(duì)自然規(guī)則的模仿2018-09-29 補(bǔ)充:也不是簡(jiǎn)單的『模仿』,有興趣可閱讀新博客『企鵝不是鳥(niǎo)』。
舉個(gè)例子,人可以喝酒,喝茶,喝可樂(lè),喝各種飲料,但人作為哺乳動(dòng)物,怎么著都能喝水吧?但反過(guò)來(lái),哺乳動(dòng)物能喝水,但不一定能喝酒喝茶喝可樂(lè),所以人是哺乳動(dòng)物的子類(lèi)。
從語(yǔ)言設(shè)計(jì)的角度來(lái)說(shuō),子類(lèi)就應(yīng)該是父類(lèi)的加強(qiáng)版,就是要能比父類(lèi)處理更多的對(duì)象類(lèi)型,而被覆寫(xiě)的方法參數(shù)類(lèi)型的擴(kuò)大,也是這一原則的體現(xiàn)。
再來(lái)說(shuō)可能有點(diǎn)繞的返回類(lèi)型,為什么子類(lèi)要縮小返回的范圍呢?其實(shí)只要假設(shè)一個(gè)方法的返回會(huì)作為另外一個(gè)方法的參數(shù),就很好想了。比如一個(gè)『水果飲料廠』類(lèi),有一個(gè)『生產(chǎn)』方法,返回『水果汁』,并傳給了『小朋友』的『喝』方法。有一個(gè)『橘子汁工廠』類(lèi)屬于『水果飲料廠』的子類(lèi),它的『生產(chǎn)』方法返回類(lèi)型縮緊,只能返回『橘子汁』,依然給『小朋友』『喝』,并不會(huì)出現(xiàn)任何問(wèn)題。
再舉一個(gè)反例。如果又出現(xiàn)一個(gè)『水果飲料廠』的子類(lèi),其『生產(chǎn)』方法除了返回水果汁,還能返回果釀酒,那這個(gè)子類(lèi)很顯然不能冒著給小朋友喝酒的風(fēng)險(xiǎn)去替換父類(lèi)。
說(shuō)完了 Liskov 替換原則,我們?cè)賮?lái)看看 7.2 里的這個(gè)改進(jìn),我們這時(shí)應(yīng)該知道其實(shí)這也是 Liskov 原則的體現(xiàn)。目前來(lái)說(shuō),替換原則在 PHP 的實(shí)現(xiàn)并不完全??赡苡腥擞X(jué)得這個(gè)版本是不是也支持『父類(lèi)沒(méi)有返回類(lèi)型,子類(lèi)可以有返回類(lèi)型』呢?遺憾的是至少在 7.2 這個(gè)版本,并不支持,大家可以自行實(shí)驗(yàn)一下。
7.2 的另外一個(gè)新功能,是 object 可以作為任何對(duì)象的類(lèi)型。見(jiàn)官方提供例子:
其實(shí)在 7.2 發(fā)布之前,也是出于替換原則,有過(guò)一次關(guān)于『是否子類(lèi)可以用 object 類(lèi)型來(lái)替代被覆蓋的方法對(duì)象參數(shù)的類(lèi)型』,但最終投票并沒(méi)有通過(guò)。雖然我不知道原因,但起碼有人提了。
另外目前 PHP 不能像 Java 那樣重載(overload),沒(méi)有辦法可以指定覆蓋的方法的類(lèi)型(目前只能把類(lèi)型直接去掉,有點(diǎn)太粗暴):
到此,關(guān)于“怎么理解PHP7.2忽略父類(lèi)方法以及Liskov替換原則相關(guān)問(wèn)題”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
網(wǎng)站題目:怎么理解PHP7.2忽略父類(lèi)方法以及Liskov替換原則相關(guān)問(wèn)題
網(wǎng)站地址:http://weahome.cn/article/gespcp.html