1、Trait组合的同名方法的命名冲突的解决方案:一是替换,用关键字insteadOf,二是别名,用关键字as,as 还可以修改trait成员的访问控制,两种命名冲突的解决方案和trait中改变trait中的访问控制的方法演示如下:
<?php
// trait功能3: trait组合实现功能扩展
trait tTest1
{
// 格式化打印类中属性
public function getProps()
{
$props =get_class_vars(__CLASS__);
printf('<pre>%s</pre>', print_r($props, true));
}
}
trait tTest2
{
// 格式化打印类中方法
public function getMethods()
{
$props =get_class_methods(__CLASS__);
printf('<pre>%s</pre>', print_r($props, true));
}
}
// 工作类
class Work1
{
// 引用多个trait, 中间用逗号分开
use tTest1, tTest2;
public $course = '编程';
public $score = 90;
protected function tablelists()
{
return $this->course . ' : ' . $this->score;
}
}
// 客户端
$work1 = new Work1();
$work1->getProps();
$work1->getMethods();
//////////////////////////////////////////////////
trait tTest3
{
// 引用多个trait, 中间用逗号分开
use tTest1, tTest2;
}
// 工作类
class Work2
{
// 只要引用一个trait组合
use tTest3;
public $course = '编程';
public $score = 66;
protected function tablelists()
{
return $this->course . ' : ' . $this->score;
}
}
// 客户端
$work2 = new Work2();
$work2->getProps();
$work2->getMethods();
// trait4: 解决trait组合中的方法命名冲突
trait tceshi1
{
public function display()
{
return __TRAIT__ . ' => ' . __METHOD__;
}
}
trait tceshi2
{
public function display()
{
return __TRAIT__ . ' => ' . __METHOD__;
}
}
trait tceshi3
{
use tceshi1, tceshi2 {
// 1. 替代
tceshi1::display insteadOf tceshi2;
// 2. 别名
tceshi2::display as td2;
}
// as: 还可以修改trait成员的访问控制
use tceshi1 {display as protected td1;}
}
// 工作类
class Work
{
use tceshi3;
}
// 客户端
$work = new Work();
echo $work->display();
echo '<hr>';
echo $work->td2();
echo '<hr>';
echo $work->td1();
2、个人感觉trait 实现接口的方法优点是可以方便不同用户对方法的调用,更好得实现代码复用;缺点可能是在trait中实现了接口的方法,如果功能不能很好的满足用户类的需求,则在类中需要重写,增加了工作量。
3、实例演示一个trait与接口,抽象类联合编程:
<?php
//水果篮
$fruits = ['苹果', '提子', '香蕉', '菠萝', '樱桃', '芒果', '油桃', '西瓜'];
// 接口
interface iCreateId
{
// 生成唯一ID
public static function generateId(int $min, int $max):int;
}
// trait: 实现接口方法
trait createId
{
public static function generateId(int $min, int $max):int
{
return mt_rand($min, $max);
}
}
// 开奖类
class DrawPrize implements iCreateId
{
use createId;
public static function award(array $fruits, int $id)
{
return $fruits[$id];
}
}
// 客户端测试
//print_r($prizes);
printf('<pre>水果篮:<br>%s</pre>', print_r($fruits, true));
echo '<hr>';
$id = DrawPrize::generateId(0,7);
$fruits = DrawPrize::award($fruits, $id);
printf('恭喜您抽到的赠送水果是: <span style="color:red">%s</span><span style="color:blue">%s斤</span>', $fruits,mt_rand(1, 8));
课程学习小结
本次课程老师从浅显易懂的实例出发,细致讲解了接口、trait及抽象类使用的相关内容,通过回看视频及讲义代码,加深了理解, 并通过修改实现trait 与接口,抽象类实战案例,完成了一个水果店赠送抽奖活动,除了水果名称之外,还加上了重量,加了点小改进。当然实例还可以再优化完善,实现“大转盘”等更直观、更具体验感的展示方式,留待后续提升练习。