trait 是什么
trait 是php5.4之后新增的一个功能,可以将某些需要反复使用代码封装到trait中,以达到代码复用的效果。trait本质上不是类,所以不支持静态成员和类常量,也无法被实例化
如果说:继承可以纵向扩展一个类,那么trait就是横向扩展一个类功能
一个简单的trait示例
<?php
trait Test1
{
public $name = 'Tom'; //trait类中可以用属性
public function demo1() //trait类中主要成员是方法
{
return 'Test1::demo1()';
}
}
trait Test2
{
function demo2()
{
return 'Test2::demo2()';
}
}
class Demo
{
use Test1, Test2;//在Demo中引入trait
}
//进行测试
$Demo = new Demo;
echo $Demo->name; //Tom
echo $Demo->demo1(); //Test1::demo1()
echo $Demo->demo2(); //Test1::demo2()
trait的嵌套
trait可以互相嵌套,一个trait类中可以用use导入另一个trait类
<?php
trait Test1
{
public $name = 'Tom'; //trait类中可以用属性
public function demo1() //trait类中主要成员是方法
{
return 'Test1::demo1()';
}
}
trait Test2
{
use Test1; //引入Test1
function demo2()
{
return 'Test2::demo2()';
}
}
class Demo
{
use Test2;//引入Test2 因为Test1包含了Test2 所以这里相当于引入了 Test1,Test2
}
//进行测试
$Demo = new Demo;
echo $Demo->name; //Tom
echo $Demo->demo1(); //Test1::demo1()
echo $Demo->demo2(); //Test1::demo2()
关于继承
当子类继承父类,且子类引入trait中的方法与父类命名冲突时,父类中的方法会被覆盖 如果子类中出现了trait中的同名方法,则trait中的同名方法被覆盖
在同一个类中,同名方法的优先级:子类>Trait类>父类,与就是说,谁离调用者越近,谁的优先级就越高。
trait Test1
{
public $name = 'Tom'; //trait类中可以用属性
public function demo1() //trait类中主要成员是方法
{
return 'Test1::demo1()';
}
}
trait Test2
{
use Test1; //引入Test1
public function demo2()
{
return 'Test2::demo2()';
}
}
class Demo
{
public function demo1()
{
return 'Demo::demo1';
}
}
class Son extends Demo
{
public function demo1()
{
return 'Son::demo1()';
}
use Test2;
}
//进行测试
$Son = new Son;
// echo $Son->name; //Tom
echo $Son->demo1(); //Son::demo1()
echo $Son->demo2(); //Test1::demo2()
trait方法同名冲突
当引入的多个trait中包含同名方法时,会引起冲突,那如何来解决这个问题呢
<?php
trait Test1
{
public function hello()
{
return 'Test1::hello()';
}
}
trait Test2
{
public function hello()
{
return 'Test2::hello()';
}
}
class Demo
{
use Test1, Test2{
Test1::hello insteadof Test2;//方法一:使用Test1中的hello替代Test2中的hello
Test2::hello as hello2;//方法二:使用别名访问
}
}
//进行测试
$Demo = new Demo;
echo $Demo->hello(); //Test1::hello()
echo $Demo->hello2(); //Test2::hello()