traits在php中的使用频率不是很高,但却是几乎和class同一级别的东西。与class一起完善单继承的同时,规避了多继承带来的问题。所以还是有必要了解一下的。
引入
Traits是在php5.4.0中引入的,所以如果项目低于这个版本,是没办法使用traits的。
概念
Traits(特性集1)是针对php这样的单继承语言设计的。旨在让开发者很方便的在不同继承体系的多个类之间公用一系列方法,以减少单继承带来的局限性。Traits和class的结合,避免了多继承带来的一些列问题。
使用
首先看下官方文档给出的例子:
<?php
trait ezcReflectionReturnInfo {
function getReturnType() { /*1*/ }
function getReturnDescription() { /*2*/ }
}
class ezcReflectionMethod extends ReflectionMethod {
use ezcReflectionReturnInfo;
/* ... */
}
class ezcReflectionFunction extends ReflectionFunction {
use ezcReflectionReturnInfo;
/* ... */
}
?>
从上面的例子可以看出,特性集ezcReflectionReturnInfo
包含了两个方法:getReturnType
和getReturnDescription
,而下面的两个子类分别继承自不同的父类,却可以通过use ezcReflectionReturnInfo
来复用这两个方法。简单方便。
注意事项
- 如果子类、父类、use的traits中存在重名方法,那么这三个方法的优先级为:子类 > tratis > 父类;
- 可以同时use多个traits,但不可use重名的traits;
- 如果use的多个traits中存在方法名冲突,可以使用指定某个方法来自于某个tratis。例如:
<?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;
}
}
- 方法可以使用as来设置别称,但只在该类有效。
class Aliased_Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
B::bigTalk as talk;
}
}
- 使用as的时候,还可以改变方法的可见性。
class MyClass2 {
use HelloWorld { sayHello as private myPrivateHello; }
}
- traits可以嵌套,例如A可以use B。
<?php
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World!';
}
}
trait HelloWorld {
use Hello, World;
}
- traits中可以定义abstract方法,同样的,use该traits的class,也需要实现这些abstract的方法;
- traits中可以定义常规变量、静态的变量和方法;
这里的特性集是作者自己翻译的名称,仅供参考; ↩︎