Peng PHP Development Engineer

PHP中的trait

2018-08-20
PHP

trait是php5.4以后新增加的一个功能,可以将多个类中,共用的一些属性和方法提取出来做来公共trait类。 trait可能大家用的不是很多,这篇文章会举出几个例子来理解如何使用trait;然后对于这个特性,由于笔者在自己的框架中有用到,也会指出具体使用场景。

介绍

php从以前到现在一直都是单继承的语言,无法同时从两个基类中继承属性和方法,为了解决这个问题,php出了Trait这个特性。 通过在类中使用use关键字,声明要组合的trait名称。 具体的trait声明则使用trait关键字,trait不能被实例化。

例子

话不多说,接下来举几个例子来理解。

基本使用实例:

trait Dog
{
    public $name = 'dog';
    public function talk()
    {
        echo 'dog talk<br>';
    }
}
class Animal
{
    public function eat()
    {
        echo 'animal eat<br>';
    }
}
class Cat extends Animal
{
    use Dog;
    public function jump()
    {
        echo 'cat jump<br>';
    }
}
$cat = new Cat();
$cat->talk();
$cat->eat();
$cat->jump();

以上会输出:

第一次输出

可以发现,在cat类中use引入trait后,能够使用trait中的方法。

trait、父类和本类存在同名方法实例:

trait Dog
{
    public $name = 'dog';
    public function talk()
    {
        echo 'dog talk<br>';
    }
    public function eat()
    {
        echo 'dog eat<br>';
    }
}
class Animal
{
    public function talk()
    {
        echo 'animal talk<br>';
    }
    public function eat()
    {
        echo 'animal eat<br>';
    }
}
class Cat extends Animal
{
    use Dog;
    public function talk()
    {
        echo 'cat talk<br>';
    }
}
$cat = new Cat();
$cat->talk();
$cat->eat();

以上会输出:

第二次输出

由此可见,trait会覆盖父类中的同名方法,而本来会覆盖trait中的同名方法。

注意,如果在类中use了某个trait,那么在此类中,不能重复定义trait中的属性不相同的值。 在上面的代码中,如果cat类定义了$name属性,那么只能定义为’dog’,否则会报错。

组合多个trait实例:

trait trait1
{
    public function talk()
    {
        echo 'trait1 talk<br>';
    }
    public function eat()
    {
        echo 'trait1 eat<br>';
    }
}
trait trait2
{
    public function talk()
    {
        echo 'trait2 talk<br>';
    }
    public function eat()
    {
        echo 'trait2 eat<br>';
    }
}
class Cat
{
    use trait1,trait2{
        trait1::talk insteadof trait2;
        trait1::eat insteadof trait2;
    }
}
class Dog
{
    use trait1,trait2{
        trait1::talk insteadof trait2;
        trait1::eat insteadof trait2;
        trait2::talk as talken;
        trait2::eat as eaten;
    }
}
$cat = new Cat();
$cat->talk();
$cat->eat();

echo '<br>';
$dog = new Dog();
$dog->talk();
$dog->eat();
$dog->talken();
$dog->eaten();

以上会输出:

第二次输出

使用场景

trait可以定义多个类的公共方法,在类中use特定的trait后,当实例化某个类时,能够调用trait中的同名方法。 也就是说,可以把多个类中相同的方法放在trait中,作为公共方法。

以下是实例化某个类时,调用trait中公共方法的例子:

trait trait1
{
    public function __construct($config = [])
    {
        if (!empty($config)) {
            foreach ($config as $key => $row) {
                $this->$key = $row;
            }
        }
        $this->init();
    }
    public function init()
    {
    }
}

class demo
{
    use trait1;
    public $name;
    public function init()
    {
        echo 'demo init';
    }
}
$demo = new demo(['name'=>'test_name']);
echo '<br>';
echo $demo->name;

以上会输出:

第二次输出

这种方式在框架中会用得比较多,特别是组件设计模式,只要在定义组件的类中引用组件trait,那么在初始化的时候,就会把组件的配置加载进去。

总结

以上就是trait的大概用法,在某些场合,使用trait会方便实现PHP无法多继承的问题。


Similar Posts

下一篇 Google Pay

Comments