PHP 中 Trait 的使用总结

最近在使用Laravel中发现好多 Trait的使用 感觉很有意思
由于php是单继承的语言 无法同时继承多个基类 但是可以使用 Trait 通过 Trait 可以很方便的实现代码的复用 类似继承的效果
Trait 不能实例化


示例一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
trait MyTime{
public $is_flag=123;
protected $is_show=0;
private $is_now=233;
/**
* 比如简单的定义一个方法就是获取当前时间一天后的
*/
public function getTime(){
return date('Y-m-d H:i:s',time()+3600*24);
}
}
class HelpTime{
//使用use关键字
use MyTime;
public function test(){
echo $this->is_show."<br/>";
echo $this->is_flag."<br/>";
echo $this->is_now."<br/>";
echo $this->getTime();
}
}
$help=new HelpTime();
$help->test();
?>

以上输出结果

1
2
3
4
123
0
233
2016-10-21 16:41:22

从上面结果可以看出如果使用use 关键字引入了一个trait 就会拥有它里面的所有属性和方法 包括私有 保护的 可以直接使用

如果需要引入多个Trait可以使用逗号隔开

1
use Trait1,Trait2;

示例二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?php
trait Human{
public function eat(){
echo "human eating";
}
public function sleep(){
echo "human sleep";
}
}
class Father{
public function eat(){
echo "father eating";
}
public function sleep(){
echo "father sleep";
}
}
class Son extends Father{
use Human;
public function eat(){
echo "son eating";
}
}
$son=new Son();
$son->eat();
$son->sleep();
?>

输出结果

1
2
son eating
human sleep

这个比较有意思了,当类中和基类和trait中存在同名的方法时候 当前类的方法会覆盖基类覆盖 Trait,而同时Trait中的会覆盖基类 这种情况同样适用于变量

示例三

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
trait Test1{
public function sayHello(){
echo "test1 say hello";
}
}
trait Test2{
public function sayHello(){
echo "test2 say hello";
}
}
class Test3{
use Test1,Test2;
}
?>

当适用的多个Trait中含有重名的方法时候会报错

1
Fatal error: Trait method sayHello has not been applied, because there are collisions with other trait methods on Test3

网上给出的解决办法 适用 insteadofas 来解决 insteadof的作用是使用前面的方法代替后面另外一个方法 而as的作用是给方法取个别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
trait Test1{
public function sayHello(){
echo "test1 say hello";
}
}
trait Test2{
public function sayHello(){
echo "test2 say hello";
}
}
class Test3{
use Test1,Test2 {
Test1::sayHello insteadof Test2;
Test2::sayHello as test2sayhello;
}
}
$test3=new Test3();
$test3->sayHello();
$test3->test2sayhello();
?>

上面这个输出结果

1
2
3
4
insteadof 那一句的作用就是使用Test1中的sayHello方法替代Test里的sayHello方法
as 那一句的作用就是直接给Test2中的sayHello方法取了个别名叫 test2sayhello
test1 say hello
test2 say hello

参考文献
tabalt
博客园


-------------The End-------------