Correcting teacher:天蓬老师
Correction status:qualified
Teacher's comments:咱们是不是学得有点太多了, 希望大家要私下多努力
当我们引用两个trait,且他们有中有一个方法同名,这是就会产生冲突,那如何解决这种冲突呢
将其中一个用另一个代替,这样就不会产生冲突了
示例:
trait tDemo1{
public function hello()
{
echo 'hello';
}
}
trait tDemo2{
public function hello()
{
echo 'the world';
}
}
trait tDemo3{
use tDemo1,tDemo2{
// 1.替代,将tDemo1的hello替代tDemo2的方法
// 这样,在调用tDemo2的时候,就会用tDemo1代替执行
tDemo1::hello insteadof tDemo2;
}
}
class Work
{
use tDemo3;
}
$work = new Work();
echo $work->hello();
echo '<hr>';
将其中一个方法,给它起一个别名,调用的时候用别名,名称不会冲突,也是一种方法
示例
trait tDemo1
{
public function hello()
{
echo 'hello';
}
}
trait tDemo2
{
public function hello()
{
echo 'the world';
}
}
trait tDemo3
{
use tDemo1,tDemo2{
// 2.别名法,将tDemo2的hello用一个其他名字代替
// 这样,在调用tDemo2的时候,就可以用别名调用
tDemo2::hello as say;
}
}
class Work
{
use tDemo3;
}
$work = new Work();
echo $work->say();
echo '<hr>';
当在trait中引用了另外一个trait,且这个trait不被别人调用时,这时就出现了trait访问控制,分别是public ,protected ,private 这三个
示例
trait tDemo1
{
public function hello()
{
echo 'hello1';
}
}
trait tDemo2
{
public function hello()
{
echo 'hello2';
}
}
trait tDemo3
{
use tDemo1,tDemo2{
// tDemo1::hello as say;
tDemo1::hello insteadOf tDemo2;
tDemo2::hello as book;
}
// 通过`as`可以修改trait成员的访问控制,
// public:表示可以访问
// protected:不可访问
// 将tHello中的hello方法设为保护的
// use tDemo2 {hello as public;}
}
class Work
{
use tDemo3;
}
$work = new Work();
echo $work->hello();
// 此时无法调用,因为hello方法已经成为受保护的了
echo $work->book();
先就从trait
说起,Trait
是一种代码复用技术,为PHP的单继承限制提供一套灵活的代码复用机制。再讲接口的优点,接口主要的优点就是多态,还有多继承,一个接口,可以让具有继承关系的不同类对象,可以对相同名称的成员调用,产生不同的反应结果。一个类还可以继承多个接口,那么trait
实现接口的优点就出来了,实现模块坏开发,当一个类继承多个接口,用trait
将每个模块实现,代码复用就体现出来了。写的代码会非常的优雅。
用trait实现接口,有几个缺点
trait
实现接口特别要注意优先级,当类中的方法与trait
中的方法重名时,优先级的关系需要搞清楚。trait
重名时,trait
的权重大于父类示例
// 随机输出一个用户的级别以及优惠力度
$Data = [
['id' => '1','name' => '张三','level' => 'normalUser'],
['id' => '2','name' => '李四','level' => 'vipUser'],
['id' => '3','name' => '王麻子','level' => 'newUser'],
];
interface iUserData
{
public static function generateId(int $min , int $max):int;
}
trait iPrint
{
static public function printLevel($level)
{
if($level == 'normalUser'):
echo '普通用户'.'<br>';
elseif ($level == 'vipUser' ):
echo 'VIP用户'.'<br>';
elseif ($level == 'newUser'):
echo '新用户'.'<br>';
else:
echo '用户不存在'.'<br>';
endif;
}
}
trait iCreateId1
{
public static function generateId(int $min , int $max):int
{
return mt_rand($min,$max);
}
}
// abstract class Discount implements iUserData
abstract class Discount implements iUserData
{
use iCreateId1;
public static function discount1($level)
{
if($level == 'normalUser'):
echo '九折'.'<br>';
elseif ($level == 'vipUser'):
echo '七折'.'<br>';
elseif ($level == 'newUser'):
echo '八折'.'<br>';
endif;
}
}
// 工作类:输出类
class User extends Discount
{
use iCreateId1,iPrint;
public static function awrad(array $Data,int $id)
{
echo '用户名称为'.$Data[$id]['name'].'<br>';
}
}
$id = User::generateId(0,2);
$user = User::printLevel($Data[$id]['level']);
$userdata = User::discount1($Data[$id]['level']);
$userdata1 = User::awrad($Data,$id);
输出:
新用户
八折
用户名称为王麻子
这个案例看似简单,如果用循环控制语句,可能几行代码就实现出来了,但是用面向对象实现出来,并不会那么简单,首先得知道数组的结构,以及函数传参,再用trait
把它们是实现一个功能模块。用抽象类实现接口的好处就是,可以只实现其中的一个方法,而不用像继承类那样,把全部的都要实现。