php面向對象之多態(1)

利用java來引入多態

買一個手電筒(說明書上寫的手電筒只能裝紅玻璃),和幾個不同顏色的玻璃片,目的是裝上不同的玻璃片,顯示不同的顏色

public class PolyTest
{
    public static void main(String[] args)
    {
        Light light = new Light();
        RedGlass rg = new RedGlass();
        BlueGlass bg = new BlueGlass();

        light.ons(rg);
        light.ons(bg);  // I want to show blue light;
    }

}

class Light    //手電筒
{
    public void ons(RedGlass red)  //對應了說明書上寫的只能裝紅玻璃
    {
        red.display();
    }
}

class RedGlass  //紅玻璃
{ 
    public void display()
    {
        System.out.println("red light");
    }
}


class BlueGlass   //藍玻璃
{
    public void display()
    {
        System.out.println("BlueGlass");
    }
}
/**
這樣一段代碼,在java中 編譯通不過.
原因是:
    public void ons(RedGlass red)
    {
        red.display();
    }

    ons方法, 指定了 接收的參數必須是  RedGlass,即紅玻璃對象
    因此,你傳一個藍光玻璃,不行!


強類型語言的一個特點,
函數參數,函數的返回值,都是定死的.

這裏寫圖片描述

改進上述java代碼

讓手電筒安裝什麼玻璃片就顯示什麼顏色
只需要讓RedGlass和BlueGlass都繼承一個父類Glass,說明書上聲明安裝玻璃Glass,不說明安裝什麼顏色的玻璃

上面程序的php實現

class Light {
    // 開燈, 傳一個玻璃參數
    public function ons($g) {        
        $g->display();  // 用玻璃渲染顏色
    }
}


class RedGlass {
    public function display() {
        echo '紅光照耀<br />';
    }
}
class BlueGlass {
    public function display() {
        echo '藍光照耀<br />';
    }
}

class GreenGlass {
    public function display() {
        echo '綠光照耀<br />';
    }
}
class Pig {
    public function display() {
        echo '八戒下凡,哼哼墜地!<br />';
    }
}
// 創建一個手電筒
$light = new Light();

// 創建3塊玻璃
$red = new RedGlass();
$blue = new BlueGlass();
$green = new GreenGlass();

// 變紅燈
$light->ons($red);

// 爲藍燈
$light->ons($blue);

// 變綠燈
$light->ons($green);


// 調用錯了
$pig = new Pig();
$light->ons($pig);  //任然何以運行
分析 與java那段出錯程序相比
php沒報錯,
因爲PHP是弱類型動態語言.

一個變量  
$var = 8;
$var = 'hello';
$var = new Pig();

一個變量,沒有類型,你裝什麼變量都行.

同理,傳參,參數也沒有強制類型.
傳什麼參都行.


所以,對於PHP動態語言來說,豈止是多態,簡直是變態.

又有專家說, 你這個太靈活了,簡直變態,不能這麼靈活.
 否則我們就不說你多態.

答:別急,我們不讓php這麼靈活還不行嗎
我對參數做類型限制總行了吧.
見下一頁

變態是因爲沒有限制類型,現在我們對參數做類型限制

限制類型的php

class Light {
    // 此處,仿java,也加一個類名,做參數類型檢測
    public function ons(RedGlass $g) {  
        // 用玻璃渲染顏色
        $g->display();
    }
}

class RedGlass {
    public function display() {
        echo '紅光照耀<br />';
    }
}

class BlueGlass {
    public function display() {
        echo '藍光照耀<br />';
    }
}

class GreenGlass {
    public function display() {
        echo '綠光照耀<br />';
    }
}

class Pig {
    public function display() {
        echo '八戒下凡,哼哼墜地!<br />';
    }
}

$light = new Light();// 造手電筒

$red = new RedGlass();// 造紅玻璃
$blue = new BlueGlass();// 造藍玻璃

$light->ons($red);// 紅燈亮
$light->ons($blue);// 出錯:atchable fatal error: Argument 1 passed to Light::ons() must be an instance of RedGlass, instance of BlueGlass given

說明:
加了類型檢測後,果然傳藍玻璃不行.
哲學: 子類是父類, 例:男人是人,白馬是馬,藍玻璃是玻璃.
里氏代換: 原能用父類的場合,都可以用子類來代替.
解決:參數定爲父類,傳其子類.

php實現

class Light {
    // 此處,仿java,也加一個類名,做參數類型檢測
    public function ons(RedGlass $g) {  //只能檢測對象,這裏即使傳入int,也是按照對象看待
        // 用玻璃渲染顏色
        $g->display();
    }
}
class Glass{
    public function display(){}
}
class RedGlass extends Glass{
    public function display() {
        echo '紅光照耀<br />';
    }
}

class BlueGlass extends Glass {
    public function display() {
        echo '藍光照耀<br />';
    }
}

class Pig {
    public function display() {
        echo '八戒下凡,哼哼墜地!<br />';
    }
}

$light = new Light();// 造手電筒

$red = new RedGlass();// 造紅玻璃
$blue = new BlueGlass();// 造藍玻璃

$light->ons($red);// 紅燈亮  成功
$light->ons($blue);//藍燈亮 成功

// 豬八戒降生
$pig = new Pig();
$light->ons($pig);  //出錯,要的是Glass對象,傳入的卻是pig對象

說明;
如果按PHP本身特點,不檢測類型,本身就可以說是多態的,甚至變態的.

但是PHP5.3以後,引入了對於對象類型的參數檢測,
注意 只能檢測對象所屬的類

其實,這對於PHP來說,限制了其靈活性,達到的java中多態的效果.

反思多態:
其實就是
只抽象的聲明父類, 具體的工作由子類對象來完成
這樣,不同的子類對象完成,有不同的特點

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章