php trait 用法注意事项

减肥是一件大事,先让我吃饱了,再来好好计划计划。

 

Trait 和类相似,支持定义方法属性,但他却不是类,不支持定义构造函数,因而不能实例化,只能被其他类使用,要在一个类中使用 Trait,可以通过 use 关键字引入,然后就可以在类方法中直接使用 trait 中定义的方法了。

trait Power {
    
    protected function gas()
    {
        return '汽油';
    }

    protected function battery()
    {
        return '电池';
    }
}

 

使用

class Car {
    use Power;

    public function drive()
    {
        echo "动力来源:" . $this->gas() . PHP_EOL;
        echo "汽车启动..." . PHP_EOL;
    }
}

 

我们可以轻松通过 Trait + 类的组合扩展类的功能,在某个类中使用了 Trait 之后,就好像把它的所有代码合并到这个类中一样,可以自由调用,并且同一个 Trait 可以被多个类复用,从而突破 PHP 单继承机制的限制,有效提升代码复用性和扩展性。

 

注意,trait 有对应的可见性,方法是private属性也可以被直接访问

trait Power {
    
    protected function gas()
    {
        return '汽油';
    }

    public function battery()
    {
        return '电池';
    }

    private function water()
    {
        return '水';
    }
}

class Car {
    use Power;

    public function drive()
    {
        echo "动力来源:" . $this->water() . PHP_EOL;
        echo "切换动力来源:" . $this->battery() . PHP_EOL;
        echo "切换动力来源:" . $this->gas() . PHP_EOL;
    }
}

$car = new Car();
$car->drive();

 

在来举个特例,在trait 中添加一个属性

trait Power {
    // 属性
    protected $power;

    protected function gas()
    {
        $this->power = '汽油';
    }

    public function battery()
    {
        $this->power = '电池';
    }

    private function water()
    {
        $this->power = '水';
    }
}

class Car
{
    use Power;

    public function drive()
    {
        // 设置动力来源
        $this->gas();
        echo "动力来源:" . $this->power . PHP_EOL;
    }
}

$car = new Car();
$car->drive();

可以看到,我们在 Trait 中可以使用 $this 指向当前 Trait 定义的属性和方法,因为 Trait 最终会被类使用,$this 也就最终对应着被使用类的对象实例。然后我们在使用类 Car 中可以通过 $this->power 调用 Trait 属性,就好像调用自己的属性一样。

注意:如此在使用的trait 类中也定义了相同的属性的名的话,会出现冲突

class Car
{
    protected $power; // 再次定义会出现问题

    use Power;

    public function drive()
    {
        // 设置动力来源
        $this->gas();
        echo "动力来源:" . $this->power . PHP_EOL;
    }
}

 

在另一篇文章中已经解释了 如何使用trait的类 和 trait 里面的方法重名使用的优先级问题

查看优先级请点击

trait Power
{
    protected $power;

    protected function gas()
    {
        $this->power = '汽油';
    }

    protected function battery()
    {
        $this->power = '电池';
    }

    // 同名方法
    public function print()
    {
        echo "动力来源:" . $this->power . PHP_EOL;
    }
}

trait Engine
{
    protected $engine;

    protected function three()
    {
        $this->engine = 3;
    }

    protected function four()
    {
        $this->engine = 4;
    }

    // 同名方法
    public function print()
    {
        echo "发动机个数:" . $this->engine . PHP_EOL;
    }
}

class Car
{
    // 这里就出出现问题 - 因为两个trait里面有同名的方法
    use Power, Engine;

    public function drive()
    {
   }

}

不过不用担心新,php 也提供了相对应的解决方法

class Car
{
    use Power, Engine {
        Engine::printText insteadof Power;
    }

    public function drive()
    {
        // 设置动力来源
        $this->gas();
        $this->four();
        $this->printText();
        echo "汽车启动..." . PHP_EOL;
    }
}

 

如果还是想调佣内部的方法,则需要如下操作

class Car
{
    use Power, Engine {
        Engine::printText insteadof Power;
        
        Power::printText as printPower;
        Engine::printText as printEngine;
    }

    public function drive()
    {
        // 设置动力来源
        $this->gas();

        $this->four();

        $this->printPower();
$this->printText();
$this->printEngine(); echo "汽车启动..." . PHP_EOL; } }

 

以上就是trait 使用的一些注意事项

 

posted @ 2022-04-25 09:01  方达达  阅读(27)  评论(0编辑  收藏  举报