什么是特质

PHP 只允许单继承。换句话说,一个类只能改变另一个类。但是如果你需要包含一些不属于父类的东西呢?在 PHP 5.4 之前,你必须具有创造性,但在 5.4 中引入了特征。特征允许你基本上将一部分类复制并粘贴到主类中

trait Talk {
    /** @var string */
    public $phrase = 'Well Wilbur...';
    public function speak() {
         echo $this->phrase;
    }
}

class MrEd extends Horse {
    use Talk;
    public function __construct() {
         $this->speak();
    }

    public function setPhrase($phrase) {
         $this->phrase = $phrase;
    }
}

所以这里我们有 MrEd,它已经扩展了 Horse。但不是所有的马匹都是如此,所以我们有一个特点。让我们注意一下这是做什么的

首先,我们定义我们的特质。我们可以将它与自动加载和命名空间一起使用(另请参阅在命名空间中引用类或函数 )。然后我们将它包含在我们的 MrEd 类中,并使用关键字 use

你会注意到 MrEd 需要使用 Talk 函数和变量而不定义它们。还记得我们关于复制和粘贴的内容吗?这些函数和变量现在都在类中定义,就好像这个类定义了它们一样。

特征与抽象类最密切相关,因为你可以定义变量和函数。你也无法直接实例化 Trait(即 new Trait())。Traits 不能强制类隐式定义类似 Abstract 类或 Interface 的函数。特征用于显式定义(因为你可以根据需要使用多个接口,请参阅接口 )。

我什么时候应该使用特质?

在考虑特质时,你应该做的第一件事就是问自己这个重要的问题

我可以通过重构代码来避免使用 Trait 吗?

通常情况下,答案是肯定的。特征是由单一继承引起的边缘情况。滥用或过度使用特征的诱惑可能很高。但请考虑 Trait 为你的代码引入了另一个来源,这意味着还有另一层复杂性。在这里的例子中,我们只处理 3 个类。但 Traits 意味着你现在可以处理的远不止这些。对于每个特征,你的类变得更难以处理,因为你现在必须引用每个特征以找出它定义的内容(并且可能发生碰撞的位置,请参阅冲突解决 )。理想情况下,你应该尽可能少地保留代码中的 Traits。