PHP - 使用无法通过 using class 访问的变量创建特征

PHP - Creating a trait with variables that cannot be accessed by the using class

问题

我有以下 PHP 代码:

trait Trait1 {
    private $secret; // I want this to be only accessible in Trait1 and not in Foo

    public function getSecret() {
        return $this->secret;
    }

    public function setSecret($secret) {
        $this->secret = $secret;
    }
}


class Foo {
    use Trait1;

    public function foo() {
        return $this->secret; // This returns the $secret in Trait1
    }

}

$foo = new Foo();
$foo->setSecret("My secret!");
echo $foo->foo();

以上代码输出"My secret"

我想要什么?

我希望函数 foo() 不能 运行 $this->secret(换句话说 return 一个 运行 时间错误)。然而不幸的是,它使用了 Trait1.

中的私有变量

为什么这是个问题?

我不喜欢这种行为的原因是,如果我不小心有一个共享相同变量名的重叠私有变量;如果您不知道您覆盖了一个私有变量,它可能会导致问题。

例如:

trait Trait1 {
    private $secret;

    public function getTraitSecret() {
        return $this->secret;
    }

    public function setTraitSecret($secret) {
        $this->secret = $secret;
    }
}

class Foo {
    use Trait1;
    private $secret; // same variable name as in Trait1

    public function setFooSecret($secret) {
        $this->secret = $secret;
    }

    public function getFooSecret() {
        return $this->secret;
    }
}

$foo = new Foo();
$foo->setTraitSecret("Trait secret!");
echo $foo->getTraitSecret(); // returns "Trait secret" as expected and wanted
echo $foo->getFooSecret(); // unfortunately also returns "Trait secret"

$foo->setFooSecret("Inner secret!");
echo $foo->getTraitSecret(); // unfortunately returns inner secret
echo $foo->getFooSecret(); // returns "Inner secret" as expected and wanted

以上代码输出类似于:

Trait secret!
Trait secret!
Inner secret!
Inner secret!

解决方案?

这个问题有好的解决办法吗?

这个问题的一个潜在解决方案是在特征中为 $secret 设置一个值,这样它就不能在 class Foo.

中使用

例如

trait Trait1 {
    private $secret = null;

    public function getTraitSecret() {
        return $this->secret;
    }

    public function setTraitSecret($secret) {
        $this->secret = $secret;
    }
}

现在下面会return一个错误:

class Foo {
    use Trait1;
    private $secret; // ERROR

    ...
}

这样,就不可能意外地 'share' 同一个变量,因为它会产生致命错误。

对两个变量使用相同的值可能只会导致警告。

https://secure.php.net/manual/en/language.oop5.traits.php

If a trait defines a property then a class can not define a property with the same name, otherwise an error is issued. It is an E_STRICT if the class definition is compatible (same visibility and initial value) or fatal error otherwise.

所以这不是一个正确的方法。