PHP 是单继承语言。Trait(特质)提供水平代码复用机制,让不相关的类共享方法集,避免多继承的菱形问题与 Mixin 类的初始化顺序混乱。Trait 不能实例化,只为组合功能而生。
<?php
trait EzcReflectionReturnInfo {
function getReturnType() { /* ... */ }
function getReturnDescription() { /* ... */ }
}
class EzcReflectionMethod extends ReflectionMethod {
use EzcReflectionReturnInfo;
}
class EzcReflectionFunction extends ReflectionFunction {
use EzcReflectionReturnInfo;
}
?>
当前类方法 > Trait 方法 > 父类方法
<?php
class Base { public function say() { echo 'Hello '; } }
trait SayWorld { public function say() { parent::say(); echo 'World!'; } }
class MyHello extends Base { use SayWorld; }
$o = new MyHello; $o->say(); // Hello World!
?>
Trait 中可用 parent:: 调用父类方法(前提是使用该 Trait 的类继承自该父类)。
<?php
trait Hello { public function say() { echo 'Hello '; } }
trait World { public function say() { echo 'World'; } }
class MyClass {
use Hello, World {
World::say insteadof Hello; // 选择 World 的 say
Hello::say as sayHello; // 别名保留 Hello 的 say
}
}
?>
insteadof 排除冲突方法as 为冲突方法起别名,可同时修改可见性<?php
trait HelloWorld { public function say() { echo 'Hello World!'; } }
class A { use HelloWorld { say as protected; } }
class B { use HelloWorld { say as private myPrivateSay; } }
?>
<?php
trait Hello { public function sayHello() { echo 'Hello '; } }
trait World { public function sayWorld() { echo 'World!'; } }
trait HelloWorld { use Hello, World; }
class MyClass { use HelloWorld; }
$o = new MyClass; $o->sayHello(); $o->sayWorld(); // Hello World!
?>
<?php
trait Hello {
public function sayHelloWorld() { echo 'Hello ' . $this->getWorld(); }
abstract public function getWorld(); // 使用类必须实现
}
class MyHello {
use Hello;
private $world;
public function getWorld() { return $this->world; }
public function setWorld($v) { $this->world = $v; }
}
?>
<?php
trait Counter {
public static $c = 0;
public static function inc() { echo ++self::$c . "\n"; }
}
class C1 { use Counter; }
class C2 { use Counter; }
C1::inc(); // 1
C2::inc(); // 1(各类独立静态变量)
?>
注意:每个使用 Trait 的类拥有独立的静态变量副本。
<?php
trait Props { public $x = 1; public $same = true; }
class Test { use Props; public $same = true; // E_STRICT
public $diff = true; // Fatal error }
?>
E_STRICTFatal error<?php
trait T { public function who() { echo __CLASS__ . ' | ' . __TRAIT__; } }
class Base { use T; }
class Child extends Base {}
$c = new Child; $c->who(); // Base | T
?>
<?php
trait Singleton {
public static function getInstance() {
static $inst = null;
$cls = __CLASS__;
return $inst ?: $inst = new $cls;
}
private function __construct() {}
private function __clone() {}
private function __wakeup() {}
}
class Foo { use Singleton; private function __construct() { $this->name = 'foo'; } }
class Bar { use Singleton; private function __construct() { $this->name = 'bar'; } }
echo Foo::getInstance()->name; // foo
echo Bar::getInstance()->name; // bar
?>
<?php
trait Foo { static function bar() { return 'baz'; } }
echo Foo::bar(); // baz
?>
Loggable、Serializable)@mixin 供 IDE 识别