PHP 面向对象高级:Trait
PHP Trait
Trait 是 PHP 5.4引入的新概念,看上去既像类又像接口,其实都不是,Trait 可以看做类的部分实现,可以混入一个或多个现有的 PHP 类中,其作用有两个:表明类可以做什么;提供模块化实现。Trait是一种代码复用技术,为 PHP 的单继承限制提供了一套灵活的代码复用机制。
为什么使用Trait
PHP 语言使用一种典型的单继承模型,在这种模型中,我们先编写一个通用的根类,实现基本的功能,然后扩展这个根类,创建更具体的子类,直接从父类继承实现。这叫做继承层次结构,很多编程语言都使用这个模式。大多数时候这种典型的继承模型能够良好运作,但是如果想让两个无关的 PHP 类具有类似的行为,应该怎么做呢?Trait 就是为了解决这种问题而诞生的。
如何使用Trait
用法
Trait 的使用方法也很简单,下面有说明的例子,即使用 use
关键字。
可能你已经注意到,命名空间(namespace
) 和 Trait 使用的都是 use
关键字,不同之处在于导入位置,命名空间在类的定义体外导入,而 Trait 在类的定义体内导入。
例子
trait Drive {
public $carName = 'trait';
public function driving()
{
echo "driving {$this->carName}\n";
}
}
class Person {
public function eat()
{
echo "eat\n";
}
}
class Student extends Person {
//使用Trait
use Drive;
public function study()
{
echo "study\n";
}
}
$student = new Student();
$student->study();
$student->eat();
$student->driving();
输出结果如下:
study
eat
driving trait
上面的例子中,Student 类通过继承 Person ,有了 eat 方法,通过组合 Drive,有了driving 方法和属性 carName。
问题
能否引入多个 Trait,如果可以,如何引入;同名方法如何处理
Trait 可以引入多个,使用逗号分隔即可
use Trait1,Trait2;
trait method1{
//定义方法
function add()
{
echo "This is add action".PHP_EOL;
}
}
trait method2{
//定义方法
function add()
{
echo "This is add action".PHP_EOL;
}
}
class Article{
//引入多个trait
use method1,method2;
}
$article = new Article();
$article->add();
输出结果
PHP Fatal error: Trait method add has not been applied, because there are collisions with other trait methods on Article.
Fatal error: Trait method add has not been applied, because there are collisions with other trait methods on Article
上面的报错是因为多个 trait 中存在同名方法
如果多个 trait 中存在同名方法,可以使用 insteadof
和as
操作符来解决问题, insteadof
是使用某个方法替代另一个方法,而 as
是给方法取一个别名 。
trait method1{
//定义方法
function add()
{
echo "This is add action of method1".PHP_EOL;
}
}
trait method2{
//定义方法
function add()
{
echo "This is add action of method2".PHP_EOL;
}
}
class Article{
use method1,method2{
//指定使用method2中的add方法,解决method1中同名方法冲突
//若同名方法存在多个,insteadof 后可跟多个,用逗号隔开
method2::add insteadof method1;
//给method1中的add方法取别名
method1::add as addArticle;
}
}
$article = new Article();
// 调用method2中的add方法
$article->add();
// 调用method1中的add方法
$article->addArticle();
输出结果
This is add action of method2
This is add action of method1
Trait 引入方法与现有方法重名时,如何解决
trait 引入方法与现有方法重名时,会优先调用类中已定义的方法,其优先级顺序为: 当前类方法>trait方法>父类方法
能否对方法进行权限控制
可以进行方法权限控制
trait method1{
//定义私有方法
private function delete()
{
echo "This si delete action" . PHP_EOL;
}
//定义受保护的方法
protected function add()
{
echo "This is add action of method1" . PHP_EOL;
}
//定义公共方法
public function index()
{
echo "This is index action" . PHP_EOL;
}
}
很棒