PHP Traits 覆盖变量

4
假设我有这个特征:
trait MyTrait{

    protected static $_statVar = 'defaultStaticVal';
    protected $_var = 'defaultVal';

}

以及使用它的类

class MyClass{

    use MyTrait;

}

我该如何更改默认值,例如:

use MyTrait{

    MyTrait::$_statVar = 'nonDefaultStaticVal';
    MyTrait->_var = 'nonDefaultVal';

}

我知道所显示的语法是不正确的,而且目前,通过简单地更改继承的特质值来更改它们是不被允许的。那么这给我留下了哪些选择/替代方案呢?


你为什么不能只是在类的构造函数或使用setter方法中更改值呢? - Crisp
构造函数在特质内部并且是私有的。我目前正在考虑使用setter方法。 - arik
一个单例特质?也许可以看看这里 -> https://dev59.com/h2w05IYBdhLWcg3wqzis,以及它使用的 init 方法来处理任何额外的构造函数配置。 - Crisp
1
不错。但是我的重点更多地放在在特质中设置默认变量值,但是为使用这些特质的某些类更改这些默认值。 - arik
3
我认为你需要重新考虑在traits中提供vars的方法,可以使用抽象类来代替,在抽象类中使用该trait,但在trait外部声明这些变量。晚期静态绑定可以处理具有不同静态值的派生类。 - Crisp
谢谢,听起来是个不错的方法。 - arik
1个回答

1

PHP扩展类和trait的启动控制

我创建了一个小助手,它可以解决大多数情况,并在类+trait启动过程中扩展您的执行优先级。下面示例中使用的数字表示设置顺序。类似于Laravel的启动机制。

一个助手类:

class TraitHelper
{
    // The helper will call the boot function on every used trait.
    static public function bootUsedTraits($obj)
    {
        $usedTraits = class_uses($obj);
        foreach ($usedTraits as $traitClass) {
        $path = explode('\\', $traitClass);
        $traitBootMethod = array_pop($path);
        $traitBootMethod = 'boot'.$traitBootMethod;
        if (method_exists($obj, $traitBootMethod)) {
            $obj->$traitBootMethod();
            }
        }
    }
}

你的类:

class MyClass{

    use MyTrait;

    // Class default values
    static protected $a = 1;
    protected $b = 2;

    function __construct()
    {
        // Class setting values before trait
        self::$a = 4;
        $this->b = 5;

        $this->traitVar = 6;


        // Trait setting values
        \TraitHelper::bootUsedTraits($this);


        // Class setting values after trait
        self::$a = 10;
        $this->b = 11;

        $this->traitVar = 12;
    }
}

你的特点:
trait MyTrait {

    // Trait default values
    protected $traitVar = 3;

    // Called on "bootUsedTraits"
    public function bootMyTrait() {
        self::$a = 7;
        $this->b = 8;

        $this->traitVar = 9;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接