iT邦幫忙

13

PHP物件導向第四課:繼承(課後補充)

明天看來是沒什麼機會寫文章了。一早要出外拍照。剛好想到我漏了一個東西沒講。
所以補上去。
先前在第二堂課時,我介紹過三個物件成員:public、private、protected。
可是我在講繼承本篇時,我忘記了這件事。
所以這邊做個課後補充。

class animal{

    private $animal = 'cat';

    private function sleep(){
        echo ' sleep';
    }

}

class dog extends animal{

}
$dog = new dog;
echo $dog->animal;
$dog->sleep();

上面這個範例中,我們可以看到父類別中的$animal屬性及sleep()方法都加上了private私有成員。
先前有講過,私有成員無法被外部程式及繼承的子類別使用。
也因此這個程式就會跑出錯誤。
但是如果今天我們希望不要被外部程式所能取得使用,但又希望能夠取得父類別的使用權限呢?
這時我們可以使用protected(保護成員)來達成這個目標。
請看以下的程式碼:

class animal{

    protected $animal = 'cat';

    protected function sleep(){
        echo ' sleep';
    }

}

class dog extends animal{

    function sleep(){
        parent::sleep();
    }

    function getAnimal(){
        return $this->animal;
    }

}
$dog = new dog;
echo $dog->getAnimal();
$dog->sleep();

我們可以看到這邊的$dog->sleep();
雖然其繼承於父類別,但是因為在子類別重寫覆載,所以同名函式會視為「public」。
但是在你做parent::sleep()時就要注意,如果父類別是用private則程式將會出錯。
另外外部程式雖然無法叫用protected的元件。
但是如果是子類別去呼叫後傳出結果,是視為子類別的public成員的功能。
簡單來說子類別呼叫父類別同功能是protected的權限,但是外部程式呼叫子類別的函式功能
是屬於public的部份。
通常保護成員的用意大致用在僅允許子類別改寫方法時可取得父類別元件功能。
但不允許外部去呼叫父類別來直接使用。

下一堂課「委派」,會是相當有趣的東西。
我先po個程式碼各位可以跑跑看。

class animal{

    function name(){
        $animal = new dog;
        return $animal->animal;
    }

    function shout(){
        $animal = new dog;
        return $animal->shout;
    }

}

class dog extends animal{

    public $animal = 'dog<br>';
    public $shout = 'BOW!';

}
$dog = new dog;
echo $dog->name();
echo $dog->shout();

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
ted99tw
iT邦高手 1 級 ‧ 2013-01-25 08:46:21

讚!灑花灑花

1
fillano
iT邦超人 1 級 ‧ 2013-01-25 12:20:54

最後的例子中,父類別理論上不會知道子類別...

在Javascript有一種繼承的作法是,資料與方法分離:

&lt;pre class="c" name="code">
function inherits(base, ext) {
  for(var i in ext) {
    if(ext.hasOwnProperty(i)) {
      base[i] = ext[i];
    }
  }
}
var data = {
  id: 1,
  name: 'me'
};
var utils = {
  talk: function() {
    if(this.name) {
      alert("it's "+this.name);
    }
  }
}
inherits(data, utils);
data.talk();//it's me

如果在php用類似的想法做,可以改寫成:

&lt;pre class="c" name="code">
&lt;?php
class p {
        function talk() {
                if($this->word)
                        echo $this->word;
        }
}
class c extends p {
        var $word = "I'm p's child.";
}
class nc extends p {
}

$i = new c();
$i->talk();//I'm p's child.
$j = new nc();
$j->talk();//nothing happen
?>

更有彈性的做法是overloading...

2
fillano
iT邦超人 1 級 ‧ 2013-01-25 12:40:20

補充,如果用php-5.4,還可以用trait來做:

&lt;pre class="c" name="code">
&lt;?php
trait p {
        function talk() {
                if($this->word)
                        echo $this->word;
        }
}
class c {
        use p;
        var $word = "I'm p's child.";
}
class nc {
        use p;
}

$i = new c();
$i->talk();
$j = new nc();
$j->talk();
?>

可惜我們目前還沒有更新到5.4

我要留言

立即登入留言