1. 程式人生 > >php面向物件之多型(1)

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中多型的效果.

反思多型:
其實就是
只抽象的宣告父類, 具體的工作由子類物件來完成
這樣,不同的子類物件完成,有不同的特點