PHP - 使用使用类

时间:2015-09-08 11:53:25

标签: php traits

问题

我有以下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(换句话说,返回运行时错误)。但遗憾的是,它使用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!

解决方案?

这个问题有一个很好的解决方案吗?

2 个答案:

答案 0 :(得分:2)

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

  

如果特征定义了属性,则类无法定义具有相同名称的属性,否则会发出错误。如果类定义兼容(相同的可见性和初始值)或其他致命错误,则为E_STRICT。

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

答案 1 :(得分:0)

此问题的一个潜在解决方案是在特征中设置$secret的值,以便它不能在类Foo中使用。

e.g。

trait Trait1 {
    private $secret = null;

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

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

现在,以下内容将返回错误:

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

    ...
}

这样,就不可能意外地分享'与生成致命错误的变量相同。

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