性状

trait, 性状,介于类和接口之间,是一种实现不完全的类, 可以被其他类使用 use 引入来实现代码复用。

since >= php 5.4

优先级

从基类继承的成员会被 trait 插入的成员所覆盖。

优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。

[运行代码]

class Base{
    public function getOne()
    {
        echo 'base';
    }
}

trait Shanghai{
    public function getOne()
    {
        return 'shanghai';
    }
}

class City extends Base{
    use shanghai;
    public function getOne()
    {
        return 'city';
    }
}

$city =  new City;
echo $city->getOne();

[执行结果]

city

冲突

Fatal error: Trait method xxx has not been applied, because there are collisions with other trait methods on xxx in...

这时候使用 insteadof 命令, 可以解决2个或者更多trait冲突

[运行代码]

trait FooTrait {
  public function fooMethod() {
        return 'foo method';
  }

  public function getRow() {
        return 'foo row';
  }
}

trait TooTrait {
    public function tooMethod() {
        return 'too method';
    }

    public function getRow() {
        return 'too row';
    }
}

trait ZooTrait {
    public function zooMethod() {
        return 'zoo method';
    }

    public function getRow() {
        return 'zoo row';
    }
}

class Boo
{
    use FooTrait, TooTrait, ZooTrait {
        ZooTrait::getRow insteadof TooTrait, FooTrait;
    }

    public function booMethod() {
        return $this->fooMethod();
    }
}

$boo = new Boo();
echo $boo->booMethod(), "\n";
echo $boo->getRow();

[执行结果]

foo method
zoo row

如果性状中使用了静态属性,如果改性状被多个类使用,静态属性是分别独立保存的,互不影响。

[运行代码]

trait TestTrait {
    public static $_bar;
}
class Foo1 {
    use TestTrait;
}
class Foo2 {
    use TestTrait;
}
Foo1::$_bar = 'Hello';
Foo2::$_bar = 'World';
echo Foo1::$_bar . ' ' . Foo2::$_bar;

[执行结果]

Hello World

参考资料