trait
- 最少PHP 5.4才可以使用
- 它是类的部分实现
- 他的出现是为了针对PHP单继承的一种弥补
下面介绍语法规则
基础版
做一个最简单的demo就是
trait Helper{
public function show(){
print "Helper";
}
}
class Example3{
use Helper;
}
$exmaple3=new Example3();
$exmaple3->show();
简单来说就是定义为trait
的类,其他的类需要调用时,只需要一个use
就可以了,当然,如果有命名空间,还需要加上命名空间。
但是还有一些别的注意点,下面就一一来解析。
private
的属性和方法也可以访问
trait Helper{
private function show(){
print "Helper";
}
}
class Example3{
use Helper;
public function showInfo(){
$this->show();
}
}
$exmaple3=new Example3();
$exmaple3->showInfo();
trait
中的private
方法,在Example3
中也可以使用。
优先级
自身方法>trait的方法>继承的方法
trait Helper{
public function show(){
print "Helper";
}
}
class Base{
public function show(){
print "Base";
}
}
class Example1 extends Base {
use Helper;
public function showInfo(){
$this->show();
}
}
class Example2 extends Base{
use Helper;
public function show(){
print "Example2";
}
}
$exmaple1=new Example1();
$exmaple1->showInfo();
print "\r\n";
$exmaple2=new Example2();
$exmaple2->show();
多个trait的情况
使用多个trait
类时,用,
将他们连接起来就行了。
trait Trait1{
}
trait Trait2{
}
class Examples{
// 使用多个 trait
use Trait1,Trait2;
}
解决冲突
还是拿上面的例子,所谓冲突就是在Trait1
和Trait2
中定义了同一个方法:
trait Trait1{
public function show(){
print "Trait1";
}
}
trait Trait2{
public function show(){
print "Trait2";
}
}
class Examples{
// 使用多个 trait
use Trait1,Trait2;
}
这个时候PHP不知道用哪一个,就会fatel_error
,而所谓解决冲突就是决定使用哪一个。
trait Trait1{
public function show(){
print "Trait1";
}
}
trait Trait2{
public function show(){
print "Trait2";
}
}
class Examples{
// 要使用 insteadof (替换)来决定使用哪个方法
use Trait1,Trait2{
Trait2::show insteadof Trait1;
}
}
$examples=new Examples();
$examples->show();
设置方法别名和修改访问控制
trait Trait1{
private function show(){
print "Trait1";
}
}
trait Trait2{
private function show(){
print "Trait2";
}
}
class Examples{
use Trait1,Trait2{
// 设置方法别名
Trait1::show as showInfo;
Trait2::show insteadof Trait1;
// 修改访问控制
Trait2::show as public;
}
}
$examples=new Examples();
$examples->show();
有以下这些注意点:
- 设置别名并不能解决冲突,他只是为一个方法设置另一个别名而已。
- 不能针对一个类下的一个方法同时设置别名和修改访问控制。
trait和trait组合
trait Trait1{
public function show(){
print "Trait1";
}
}
trait Trait2{
use Trait1;
public function show(){
print "Trait2";
}
}
class Examples{
use Trait2;
}
$examples=new Examples();
$examples->show();
很简单,就是可以在trait
中可以调用trait
。
trait支持设置抽象方法
trait Trait1{
public function show(){
print "Trait1";
}
// 定义了一个抽象方法
abstract function showInfo();
}
trait Trait2{
use Trait1;
public function show(){
print "Trait2";
}
}
class Examples{
use Trait2;
function showInfo()
{
// TODO: Implement showInfo() method.
}
}
$examples=new Examples();
$examples->show();
注意:
trait
组合时,另一个trait
不需要实现该抽象方法,只有在最后可以被示例化的类中才需要实现该方法。
trait定义静态属性
trait Helper{
static $count=0;
public static function show($message=""){
print "\r\n".$message."\r\n";
}
public function getCount(){
self::$count++;
self::show("count:".self::$count);
}
}
class Example7{
use Helper;
}
class Example8{
use Helper;
}
$example7=new Example7();
$example8=new Example8();
$example7->getCount();
$example8->getCount();
输出:
1
1
注意,这里我们调用的是定义在trait
中的static $count
,并且让两个类使用了其中的getCount
方法,以静态属性的习惯,我们原本以为会得到:
1
2
但是结果不是,所以即使是静态属性,当被2个类调用时,这个静态属性也不会互相影响,所以大家可以放心使用。
属性
Trait 定义了一个属性后,类就不能定义同样名称的属性,否则会产生 fatal error。 有种情况例外:属性是兼容的(同样的访问可见度、初始默认值)。 在 PHP 7.0 之前,属性是兼容的,则会有 E_STRICT 的提醒。