Php实现多继承

  • php自身并不支持多继承,但是可以用过Trait实现多继承。

  • Trait和Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。

  • 代码实例

    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
    trait ezcReflectionReturnInfo {

    public function __construct()
    {
    echo 'ezcReflectionReturnInfo';
    }

    function getReturnType() {
    echo 'getReturnType';
    }
    function getReturnDescription() {
    echo 'getReturnDescription';
    }
    }

    class ezcReflectionMethod extends ReflectionMethod {
    use ezcReflectionReturnInfo;
    /* ... */

    }

    class ezcReflectionFunction extends ReflectionFunction {
    use ezcReflectionReturnInfo;
    /* ... */
    }

    $a = new ezcReflectionMethod();
    $b = new ezcReflectionFunction();
  • 优先级

    • 从基类继承的成员会被 trait 插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。
      例:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <?php
    class Base {
    public function sayHello() {
    echo 'Hello ';
    }
    }

    trait SayWorld {
    public function sayHello() {
    parent::sayHello();
    echo 'World!';
    }
    }

    class MyHelloWorld extends Base {
    use SayWorld;
    }

    $o = new MyHelloWorld();
    $o->sayHello(); //Hello World!
    ?>

    覆盖:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <?php
    trait HelloWorld {
    public function sayHello() {
    echo 'Hello World!';
    }
    }

    class TheWorldIsNotEnough {
    use HelloWorld;
    public function sayHello() {
    echo 'Hello Universe!';
    }
    }

    $o = new TheWorldIsNotEnough();
    $o->sayHello();
    ?>
  • 冲突解决

    • 如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。
    • 为了解决多个 trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。
    • as 操作符可以将其中一个冲突的方法以另一个名称来引入。