PHP中的Trait使用介绍

一年多没有写公众号文章了,当然这一年也没有怎么新增关注用户,还好老用户基本没有流失。现在开始重新不定期更新公众号文章,给大家传递最有价值的编程技术。希望大家喜欢,最好能转发支持。

废话不多说,下面进入正文:

PHP是单继承语言,为了使开发人员在不同层次结构内独立的类中复用方法,PHP5.4.0起,PHP实现了一种代码复用的方法Trait,Trait无法自身实例化,通过和Class组合的方式实现多继承。

示例

优先级 派生类>trait>基类

traitA {

publicfunctionsayHello(){

echo"Hello trait\n";

}

publicfunctionsayHi(){

echo"Hi trait\n";

}

}

classB{

publicfunctionsayHello(){

echo"Hello class\n";

}

publicfunctionsayHi(){

echo"Hi class\n";

}

}

classCextendsB{

useA;

publicfunctionsayHello(){

echo"Hello C\n";

}

}

$c =newC();

$c->sayHello();

$c->sayHi();

多个trait,用英文逗号分隔。

traitHello {

publicfunctionsayHello(){

echo"Hello ";

}

}

traitWorld {

publicfunctionsayWorld(){

echo"World";

}

}

classTest{

useHello,World;

publicfunctionsayHelloWorld(){

echo"!\n";

}

}

$test =newTest();

$test->sayHello();

$test->sayWorld();

$test->sayHelloWorld();

解决冲突

traitA {

publicfunctionsayHello(){

echo"Hello A\n";

}

publicfunctionsayHi(){

echo"Hi A\n";

}

}

traitB {

publicfunctionsayHello(){

echo"Hello B\n";

}

publicfunctionsayHi(){

echo"Hi B\n";

}

}

classC{

// 使用insteadof操作符明确指定使用冲突方法中的哪一个

useA,B{

A::sayHelloinsteadofB;

B::sayHiinsteadofA;

}

}

classD{

useA,B{

A::sayHelloinsteadofB;

B::sayHiinsteadofA;

A::sayHiashi;// as操作符为某个方法引入别名,解决多个trait都插入一个同名方法的冲突

}

}

$c =newC();

$c->sayHello();

$c->sayHi();

echo"\n";

$d =newD();

$d->sayHello();

$d->sayHi();

使用as语法调整方法的访问控制

traitHello {

publicfunctionsayHello(){

echo"Hello trait\n";

}

}

classA{

useHello{

Hello::sayHelloasprotected;// 使用as操作符修改sayHello的访问控制

}

}

classB{

useHello{

Hello::sayHelloasprivatesayHi;// 使用as操作符给sayHello引入一个别名并修改别名的访问控制,原版sayHello的访问控制不改变

}

}

$a =newA();

// PHP Fatal error: Uncaught Error: Call to protected method A::sayHello() from context '' in trait5.php:158

$a->sayHello();

$b =newB();

$b->sayHello();

// PHP Fatal error: Uncaught Error: Call to private method B::sayHi() from context '' in trait5.php:162

$b->sayHi();

使用trait组合trait

traitHello {

publicfunctionsayHello(){

echo"Hello ";

}

}

traitWorld {

publicfunctionsayWorld(){

echo"World!\n";

}

}

traitHelloWorld {

useHello,World;

}

classHi{

useHelloWorld;

}

$hi =newHi();

$hi->sayHello();

$hi->sayWorld();

trait使用抽象方法,对组合trait的类施加强制要求

traitHello {

publicfunctionsayHello(){

echo"Hello ".$this->getWorld();

}

// 抽象方法

abstractpublicfunctiongetWorld();

}

classHi{

private$world;

useHello;// 组合trait

// 实现抽象方法

publicfunctiongetWorld(){

return$this->world;

}

publicfunctionsetWorld($val){

$this->world = $val;

}

}

$hi =newHi();

$hi->setWorld("world!\n");

$hi->sayHello();

trait定义静态属性和静态方法

traitCounter {

publicfunctioninc(){

// 静态属性

static$c =;

$c = $c +1;

echo"$c\n";

}

// 静态方法

publicstaticfunctiondoSomething(){

return"Doing Something\n";

}

}

classTest{

useCounter;

}

$test =newTest();

$test->inc();

echo$test::doSomething();

$test->inc();

trait定义属性

traitA {

public$name ='frankphper';

public$age =18;

}

classB{

useA;

public$name ='frankphper';

public$age =28;

}

$b =newB();

echo$b->name;// PHP 7.0.0 后没问题,之前版本是 E_STRICT 提醒

echo"\n";

echo$b->age;// PHP Fatal error: B and A define the same property ($age) in the composition of B. However, the definition differs and is considered incompatible. Class was composed in trait5.php on line 250

echo"\n";

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180327G00QA600?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券