iT邦幫忙

13

PHP物件導向的第五課:介面(interface)&虛擬類別

我犯了一個過錯。
沒有先講介面的話,委派的範例不是很好寫。
先來一張UML圖,這次發表文章又有點趕時間了。

所以這一課,我想還是先講介面。
在物件導向中,所謂的介面,我們可以當成是對物件的方法定義一個規範。
任何要在我們的物件所有的功能,都必須遵從介面所定義的法方去實作該方法。
即使該方法是「什麼都沒有」,你仍然要把該方法實作出來。

interface action{

    public function run();
    
}

class animal implements action{
           
}

基本上,上面這一段code。
光是直接執行就會告訴你錯誤。
錯誤原因是因為你的物件要求實現action這個interface。
可是你並沒有把run()這個方法寫進你的物件。
上面有看到implements這個語法,這就是要求物件實現方法的語法。

因此我們必須做這樣的動作:

interface action{

    public function run();
    
}

class animal implements action{
    
    function run(){
        
    }
    
}

因為你實現了這個方法,所以這段code就會通過編譯。

現在我們用之前的動物跟狗為例子。
寫了一個需要實現介面的方式。

interface action{

    public function run();
    public function fast();
    
}

class animal implements action{
    
    function run(){
        $this->fast();
    }
    
    function fast(){
        
    }
    
}

class dog extends animal{
    
    function fast(){
        echo 'very fast';
    }
    
}

$dog = new dog;
$dog->run();

這邊要注意的是說,介面基本上父類別一但實作,子類別繼承時該方法就會存在。
所以基本上父類別有寫的情形下,子類別可以不用寫,除非你想做覆載。
但是這邊就有一個問題存在了。
比如說狗跑的快,貓跑的慢一點點。
可是父類別定義的fast()卻是空的。
這表示一但狗繼承父類別,卻不設定他跑的速度的話,就無法確知狗到底是跑的快還是慢。
因此,我們或許會希望這樣。

class animal implements action{
    
    function run(){
        $this->fast();
    }
    
}

class dog extends animal{
    
    function fast(){
        echo 'very fast';
    }
    
}

但很不幸的,你如果這樣做。
系統會告訴你animal並未宣告run()這個方法。
最主要是因為前面講過,一但子類別被實作,等同於父類別也被實作。
但父類別實作時卻沒有run()這個方法。
違反了介面的使用定義。
但今天的問題是說,fast()方法應該由子類別來實作,而不是我父類別來產生。
也就是繼承體必須自行去實作fast() (而且是強迫實作,就算是空的也要寫出來)

今天既然問題出在子類別被實作(new)時,父類別也被實作的話,有沒有可能讓父類別不被實作?
有的,這個方法就是實作一個虛擬類別:

abstract class animal implements action{
    
    function run(){
        $this->fast();
    }
    
}

上面的abstract表示宣告animal類別是一個虛擬類別。
當子類別被new的時候,animal不會被實現。
但要注意的是,通常父類別當然也可以自己被new實作出來。
但是你一但宣告abstract的話,下面這段code就一定會出錯:

abstract class animal{

}
$animal = new animal;

因為你不可以實現虛擬類別。

也因此,我們的code就會如下實現:

interface action{

    public function run();
    public function fast();
    
}

abstract class animal implements action{
    
    function run(){
        $this->fast();
    }
    
}

class dog extends animal{
    
    function fast(){
        echo 'very fast';
    }
    
}

$dog = new dog;
$dog->run();

因為父類別已經宣告為虛擬類別,所以不會產生實體。
但是因為子類別繼承父類別,所以連同介面都必須遵照action所定義的規範。
因此dog必須實作出fast()才行。

今天只是利用一點時間把介面先講完。
這樣才有利我接下來要講的委派 => 在物件中引用其他物件,尤其必須要遵從固定的介面。

今天沒去司法院抗議的。
請在心中支持現在抗議的民眾。
值日生記得關窗戶、關門。明天又放假了。


0
總裁
iT邦好手 1 級 ‧ 2013-02-01 17:11:05

tkdmaf提到:
沒去司法院抗議的

原來今天不是去立法院....瞎

0
la6972
iT邦好手 1 級 ‧ 2013-02-02 00:57:57

iT邦幫忙MVPcdfu提到:
原來今天不是去立法院

還好不是去行政院聽22K院長放...屁。

0
uuuyyttu
iT邦新手 5 級 ‧ 2015-10-25 13:33:35

咦?請問版主還未繼續出嗎?感覺超級詳細的說

那個時候後來因為工作忙碌就暫時停止寫下去。
現在則是有太多東西想要講反而還沒整理好資料。
因為有不少的變革一直在持續著。

0
aquilashih
iT邦新手 5 級 ‧ 2016-01-15 17:09:19

請教版主何時會再釋出教學呢?

收穫超多的!!感謝版主^^

0
robinnpca
iT邦新手 5 級 ‧ 2017-12-08 13:38:26

上到第五節就沒了~
我都有乖乖擦黑板
扶老太太過馬路
老師快快回來上課啦!/images/emoticon/emoticon08.gif

我要留言

立即登入留言