trait类的应用
1、trait应用场景1:代码复用
// 在trait类中定义方法,在不同类中调用
trait tDemo
{
public function show($name,$like,$gender)
{
printf('我叫%s,是个%s的%s孩。',$name,$like,$gender);
}
}
class User1
{
use tDemo;
protected $name = '张三';
protected $gender = '男';
protected $like ='爱打篮球';
public function introduce(){
return $this->show($this->name,$this->like,$this->gender);
}
}
class User2
{
use tDemo;
protected $name = '李丽';
protected $gender = '女';
protected $like ='爱跳舞';
public function introduce(){
return $this->show($this->name,$this->like,$this->gender);
}
}
(new User1)->introduce();
echo '<hr>';
(new User2)->introduce();
- 输出结果如下:
2、trait应用场景1:实现功能扩展
trait tDemo1
{
// 打印所有属性
public function getProps()
{
printf('<pre>%s</pre>', print_r(get_class_vars(__CLASS__), true));
}
}
trait tDemo2
{
// 打印所有方法
public function getMethods()
{
printf('<pre>%s</pre>', print_r(get_class_methods(__CLASS__), true));
}
}
trait tDemo3
{
use tDemo1, tDemo2;
}
class Demo1
{
use tDemo1, tDemo2; //可引用多个trait实现功能扩展
protected $name = '张三';
protected $gender = '男';
public function show()
{
return $this -> getProps();
}
}
class Demo2
{
use tDemo3; //tDemo3引入了tDemo1、tDemo2,此时只引入一个trait就可以
protected $name = '李丽';
protected $gender = '女';
public function show()
{
return $this -> getProps();
}
}
echo '<h3>Demo1</h3>';
echo '类属性:<br>', (new Demo1)->getProps();
echo '类方法:<br>', (new Demo1)->getMethods();
echo '<hr>';
echo '<h3>Demo2</h3>';
echo '类属性:<br>', (new Demo2)->getProps();
echo '类方法:<br>', (new Demo2)->getMethods();
3、trait 和 interface的组合
// 接口
interface iDemo
{
public static function index();
}
// trait
trait tDemo
{
// 将接口中的抽象方法的实现过程放在trait中实现,并在工作类中调用
public static function index()
{
return __METHOD__;
}
}
// 实现类
class Hello implements iDemo
{
use tDemo;
}
// 客户端
echo Hello::index();
输出:tDemo::index
4、trait组合中命名冲突的解决方案
trait Demo1
{
public function show()
{
return '我是:'.__METHOD__;
}
}
trait Demo2
{
public function show()
{
return '我是:'.__METHOD__;
}
}
trait Demo3
{
use Demo1, Demo2 {
// 给Demo2::show()起个别名: S2
Demo2::show as ds2;
// 调用Demo1::show()替换成Demo2::show()
Demo1::show insteadOf Demo2;
}
}
// 工作类尽可能写得代码清晰,简洁
class Demo
{
use Demo3;
}
echo (new Demo)->show();
echo '<hr>';
// 别名访问Demo2::show
echo (new Demo)->ds2();
5、trait 在继承的上下文中的优先级关系
trait Demo
{
public static function hello()
{
return 'trait中的方法' . __METHOD__;
}
}
// 父类
class Father
{
use Demo;
public static function hello()
{
return '父类中的方法' . __METHOD__;
}
}
// 子类
class Son extends Father
{
use Demo;
public static function hello()
{
return '子类中的方法' . __METHOD__;
}
}
echo son::hello();
// 在继承的上下文中存在同名方法的时候,优先级关系不同,其优先级关系如下:
// 父类引入:优先级关系为: Son > Father > trait(Demo)
// 子类引入:优先级关系为: Son > trait(Demo) > Father
输出结果请自行测试
总结:
Trait不同于继承,定义一个trait类,使用use关键字引入,在一个类中引入Trait类后,相当于require或include了一段代码进来,Trait类的成员及方法可以看做是当前类成员或方法。