1. 程式人生 > >PHP之Trait詳解(多繼承)

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
     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    <?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 方法
     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    <?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,可以都插入到一個類中。
     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    <?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 操作符來明確指定使用衝突方法中的哪一個。

     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    <?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 中的部分或全部成員。
     

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    <?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