trait类相关笔记

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;
}

解决冲突

还是拿上面的例子,所谓冲突就是在Trait1Trait2中定义了同一个方法:

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 的提醒。

发布了184 篇原创文章 · 获赞 72 · 访问量 40万+

猜你喜欢

转载自blog.csdn.net/YQXLLWY/article/details/89343240
今日推荐