PHP代碼的多繼承 -》 PHP代碼復用新的姿勢 trait


本文參考:  http://php.net/language.oop5.traits 

一、什么是trait

    從PHP 5.4.0 開始 PHP 實現了一種新的代碼復用方式 trait。

二、trait解決了什么問題

    trait 的出現是為了解決類似PHP的單繼承語言而准備的一種代碼復用機制,讓開發人員能夠在不能層次結構內獨立的類中復用 method。

三、跟其它語言相比,trait 有什么 好處

    Trait 和 Class 組合的語義定義了一種減少復雜性的方式,避免傳統多繼承和 Mixin 類相關典型問題。

四、該如何使用trait

  • 示例1,如何使用 trait

    <?php
    trait ezcReflectionReturnInfo {
        function getReturnType() { /*1*/ }
        function getReturnDescription() { /*2*/ }
    }
    
    class ezcReflectionMethod extends ReflectionMethod {
        use ezcReflectionReturnInfo;
        /* ... */
    }
    
    class ezcReflectionFunction extends ReflectionFunction {
        use ezcReflectionReturnInfo;
        /* ... */
    }
    ?>
    

     

  • 示例2 ,trait 與 class 方法優先級問題
    trait 方法會覆蓋基類中的方法,當前類中的方法會覆蓋 trait 方法

    <?php
    class Base {
        public function sayHello() {
            echo 'Hello ';
        }
    }
    
    trait SayWorld {
        public function sayHello() {
            parent::sayHello();
            echo "World!\r\n";
        }
    }
    
    class MyHelloWorld extends Base {
        use SayWorld;
    }
    
    class MyNewHelloWorld extends Base{
        use SayWorld;
        public function sayHello(){
    	echo "Hello sunshine!\r\n";
        }
    }
    
    $o = new MyHelloWorld();
    $o->sayHello();
    
    $b = new MyNewHelloWorld();
    $b->sayHello();
    ?>
    

    上面的代碼會輸出:



  • 示例3  同時使用多個 trait  通過逗號分隔,在 use 聲明列出多個 trait,可以都插入到一個類中。

    <?php
    trait Hello {
        public function sayHello() {
            echo 'Hello ';
        }
    }
    
    trait World {
        public function sayWorld() {
            echo 'World';
        }
    }
    
    class MyHelloWorld {
        use Hello, World;
        public function sayExclamationMark() {
            echo '!';
        }
    }
    
    $o = new MyHelloWorld();
    $o->sayHello();
    $o->sayWorld();
    $o->sayExclamationMark();
    ?>
    

    上面的代碼會輸出:

  • 示例4 沖突的解決 

    如果兩個 trait 都插入了一個同名的方法,如果沒有明確解決沖突將會產生一個致命錯誤。

    為了解決多個 trait 在同一個類中的命名沖突,需要使用 insteadof 操作符來明確指定使用沖突方法中的哪一個。


    <?php
    trait A {
        public function smallTalk() {
            echo 'a';
        }
        public function bigTalk() {
            echo 'A';
        }
    }
    
    trait B {
        public function smallTalk() {
            echo 'b';
        }
        public function bigTalk() {
            echo 'B';
        }
    }
    
    class Talker {
        use A, B {
            B::smallTalk insteadof A;
            A::bigTalk insteadof B;
        }
    }
    
    class Aliased_Talker {
        use A, B {
            B::smallTalk insteadof A;
            A::bigTalk insteadof B;
            B::bigTalk as talk;
        }
    }
    ?>
    

     

  • 示例5  使用trait來組成trait   正如 class 能夠使用 trait 一樣,其它 trait 也能夠使用 trait。在 trait 定義時通過使用一個或多個 trait,能夠組合其它 trait 中的部分或全部成員。

    <?php
    trait Hello {
        public function sayHello() {
            echo 'Hello ';
        }
    }
    
    trait World {
        public function sayWorld() {
            echo 'World!';
        }
    }
    
    trait HelloWorld {
        use Hello, World;
    }
    
    class MyHelloWorld {
        use HelloWorld;
    }
    
    $o = new MyHelloWorld();
    $o->sayHello();
    $o->sayWorld();
    ?>
    

    上面例子會輸出:



除了這些特性,trait 還包括 抽象成員  靜態成員  靜態方法  屬性 等特性,可以參考    http://php.net/language.oop5.traits  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM