相信大家对trait都不陌生。早在5.4时,traits就已经出现在PHP的新特性中。当然,trait本身也意味着一个特性,但这个特性的主要能力是为了代码复用。我们都知道PHP是一种现代的面向对象语言。为了解决C++多重继承的混乱问题,大多数语言都采用了单继承、多接口的形式,但这也使得一些可重用的代码必须通过组合来实现。如果要组合使用,免不了要使用实例化一个类或者使用静态方法,无形中增加了内存占用。为了解决这个问题,PHP官方推出了trait能力。您可以将其视为组合能力的变体。特征A{public$a='A';publicfunctiontestA(){echo'这是'.$这个->一个;}}classclassA{使用A;}cl??assclassB{使用A;公共函数__construct(){$this->a='B';}}$a=newclassA();$b=newclassB();$a->testA();$b->testA();从上面的代码中,我们可以看出trait可以应用于任何类,并且可以定义变量,非常方便。关于traits最需要注意的是同名方法的重载优先级。traitB{functiontest(){echo'ThisistraitB!';}}traitC{functiontest(){echo'ThisistraitC!';}}classtestB{使用B,C;functiontest(){echo'这是testB类!';}}$b=newtestB();$b->test();//这是classtestB!//classtestC{//useB,C;//}//$c=newtestC();//$c->test();//Fatalerror:Trait方法test没有应用,因为这里和testC上的其他trait方法有冲突,在我们类中重载了test()方法,这里输出的是类中的方法。如果注释掉testB类中的test()方法,会报错。因为程序无法区分你要使用哪个trait的test()方法。我们可以使用insteadof来指定用方法调用哪个特征。classtestE{使用B,C{B::testinsteadOfC;C::test作为testC;}}$e=newtestE();$e->test();//这是特征B!$e->testC();//这是特征C!当然,在实际开发中,还是尽量规范方法名,避免这样的重复。另外,如果子类引用特征并且超类定义相同的方法怎么办?当然是调用父类继承的方法。trait的优先级低于普通的类继承。traitD{functiontest(){echo'这是traitD!';}}classparentD{functiontest(){echo'这是classparentD';}}classtestDextendsparentD{使用D;}$d=newtestD();$d->test();//这是特征D!最后,抽象方法也可以定义在traits中。该抽象方法是引用该trait的类必须实现的方法,与抽象类中的抽象方法具有相同的作用。traitF{functiontest(){echo'ThisistraitF!';}abstractfunctionshow();}classtestF{使用F;functionshow(){echo'这是testF类!';}}$f=newtestF();$f->test();$f->show();trait确实是PHP非常灵活的一个函数。当然,越是灵活的东西,我们就越需要了解它的一些使用规则,以免出现一些不可预见的错误。测试代码:https://github.com/zhangyue0503/dev-blog/blob/master/php/201912/source/trait%E8%83%BD%E5%8A%9B%E5%9C%A8PHP%E4%B8%AD%E7%9A%84%E4%BD%BF%E7%94%A8.php参考文档:https://www.php.net/manual/zh/language.oop5.traits.php各媒体平台You可以搜索【硬核项目经理】
