PHP中的traits实现代码复用使用实例
PHP5.4后新增traits实现代码复用机制,Trait和类相似,但不能被实例化,无需继承,只需要在类中使用关键词use引入即可,可引入多个Traits,用','隔开。
(1)Trait简单使用
<?php
traitA{
public$var1='test1';
publicfunctiontest1(){
echo'traitA::test1()';
}
}
traitB{
public$var2='test2';
publicfunctiontest2(){
echo'traitB::test2()';
}
}
classC{
useA,B;
}
$c=newC();
echo$c->var1;//test1
$c->test2();//traitB::test2()
(2)优先级问题
Trait会覆盖继承的方法,当前类会覆盖Trait方法。
traitA{
public$var1='test';
publicfunctiontest(){
echo'A::test()';
}
publicfunctiontest1(){
echo'A::test1()';
}
}
classB{
publicfunctiontest(){
echo'B::test()';
}
publicfunctiontest1(){
echo'B::test1()';
}
}
classCextendsB{
useA;
publicfunctiontest(){
echo'c::test()';
}
}
$c=newC();
$c->test();//c::test()
$c->test1();//A::test1()
(3)多个Trait冲突问题
如果没有解决冲突,会产生致命错误;
可用insteadof来明确使用冲突中哪一个方法;
可用as操作符将其中一个冲突方法另起名;
traitA{
publicfunctiontest(){
echo'A::test()';
}
}
traitB{
publicfunctiontest(){
echo'B::test()';
}
}
classC{
useA,B{
B::testinsteadofA;
B::testast;
}
}
$c=newC();
$c->test();//B::test()
$c->t();//B::test()可以用as另起名
(4)as可用来修改方法访问控制
traitHelloWorld{
publicfunctionsayHello(){
echo'HelloWorld!';
}
}
//修改sayHello的访问控制
classA{
useHelloWorld{sayHelloasprotected;}
}
//给方法一个改变了访问控制的别名
//原版sayHello的访问控制则没有发生变化
classB{
useHelloWorld{sayHelloasprivatemyPrivateHello;}
}
$b=newA();
$b->sayHello();//Fatalerror:CalltoprotectedmethodA::sayHello()fromcontext''
(5)Trait中使用Trait
traitA{
publicfunctiontest1(){
echo'test1';
}
}
traitB{
publicfunctiontest2(){
echo'test2';
}
}
traitC{
useA,B;
}
classD{
useC;
}
$d=newD();
$d->test2();//test2
(6)Trait支持抽象方法、支持静态方法、不可以直接定义静态变量,但静态变量可被trait方法引用。
traitA{
publicfunctiontest1(){
static$a=0;
$a++;
echo$a;
}
abstractpublicfunctiontest2();//可定义抽象方法
}
classB{
useA;
publicfunctiontest2(){
}
}
$b=newB();
$b->test1();//1
$b->test1();//2
(7)Trait可定义属性,但类中不能定义同样名称属性
traitA{
public$test1;
}
classB{
useA;
public$test2;
}