php中的traits

traits是php又一实现代码复用的方法,如abstract,interface。 
给我的感觉就是php实现多继承的又一出路。

使用trait

trait的声明语法跟class几乎无异,然后在类中使用use语句来插入trait。Trait 无法像 Class 一样使用 new 实例化!

包含单个trait

trait A {
  public function demo1() {
    echo 'This is the demo1' . PHP_EOL;
  }
}

class Base {
  use A;
}

$obj = new Base();
$obj->demo1();
/*
输出:
This is the demo1
*/

包含多个trait

// trait A 同上 
trait B {
  public function demo2() {
    echo 'This is the demo2' . PHP_EOL;
  }
}
class Base {
  use A, B;
}

$obj = new Base();
$obj->demo1();
$obj->demo2();
/*
输出:
This is the demo1
This is the demo2
*/

trait中包含trait

// trait A, B同上
trait C {
  use A, B;
}

命名冲突

trait中的属性与当前类属性的命名冲突

当trait中的属性跟当前类的属性发生命名冲突时将产生错误,分有2种情况

+ 当两者的访问控制(public...)和初始值相同时,产生一个E_STRICT错误
+ 否则将产生 致命错误

如下,将产生一个致命错误(初始值不同)

trait A {
  public $bool = true;
}
class Base {
  use A;
  public $bool;
}
$obj = new Base();

trait中的方法与基类中的方法的命名冲突

如果当前类是派生类,则trait会直接覆盖基类中的方法 
如下

trait A {
  public function say() {
    echo 'This is traitA::say' . PHP_EOL;
  }
}
class Base {
  public function say() {
    echo 'This is the Base::say' . PHP_EOL;
  }
}
class ExBase {
  use A;
}

$obj = new ExBase();
$obj->say();
/*
输出:
This is traitA::say
*/

trait中的方法与当前类方法的命名冲突

类方法将覆盖trait中的方法

// trait同上
class Base {
  public function say() {
    echo 'This is the Base::say' . PHP_EOL;
  }
  use A;
}
$obj = new Base();
$obj->say();
/*
输出:
This is the Base::say
*/

trait中的方法与trait中的方法的命名冲突

如果没有明确解决2个trait间的方法名的冲突的话,将产生一个致命错误 
如下,将产生一个致命错误

trait A {
  public $a;
  public function demo1() {
    echo 'This is traitA demo1' . PHP_EOL;
  }
}
trait B {
  public function demo1() {
    echo 'This is traitB demo1' . PHP_EOL;
  }
}
class Base {
  use A, B;
}
  • 使用insteadof
// trait A, B同上
class Base {
  use A, B {
    // 用A::demo1覆盖B中的同名方法
    A::demo1 insteadof B;
  }
}
  • 再使用as 
    在使用insteadof后若想使用被覆盖的方法可使用as来别名引用
// trait A, B同上
class Base {
  use A, B {
    // 用A::demo1覆盖B中的同名方法
    A::demo1 insteadof B;
    B::demo1 as demoB;
  }
}
$obj = new Base;
$obj->demo1();
$obj->demoB();
/*
输出:
This is traitA demo1
This is traitB demo1
*/
  • as 的另一作用 
    使用 as 语法还可以用来调整方法的访问控制 
    如下,在访问demoB方法时将产生致命错误(试图访问一个private方法)
// trait A, B同上
class Base {
  use A, B {
    // 用A::demo1覆盖B中的同名方法
    A::demo1 insteadof B;
    B::demo1 as private demoB;
  }
}
$obj = new Base;
$obj->demoB();

trait中抽象与静态

trait中的抽象

跟普通抽象相同,其作用及导致结果与普通abstract一样。

trait A {
  public $a;
  abstract public function say();
}

trait中的静态成员

trait中不能定义static属性,但在方法中可以 
如下,同普通static变量

trait A {
  public function say() {
    static $cut = 1;
    ++$cut;
    return $cut;
  }
}

trait中的静态方法

同普通的静态方法

trait A {
  public static function say() {
    return 'This is a static function' . PHP_EOL;
  }
}
class Base {
  use A;
}
$obj = new Base;
echo Base::say();
echo $obj->say(); // php 5.3后支持
/*
输出
This is a static function
This is a static function
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值