36

为什么我们不允许在 PHP 中使用类扩展 Traits?

例如:

Trait T { }

Class C use T {}
/* or */
Class C extends T {}

这种语法有什么潜在的冲突吗?我不这么认为。

4

3 回答 3

45

PHP手册是这样说的:

Traits 是一种在 PHP 等单继承语言中重用代码的机制。Trait 旨在通过使开发人员能够在生活在不同类层次结构中的几个独立类中自由地重用方法集来减少单继承的一些限制。Traits 和类组合的语义以降低复杂性的方式定义,并避免与多继承和 Mixins 相关的典型问题。

如果你想扩展一个特征,那么它可能应该是一个类。如果您想在一个类中使用一组方法并希望在其他类中使用,但感觉不适合扩展该类(例如。class Animal extends Vehicle),那么在 PHP 5.4 中它可以作为一个 trait 很好地工作。

为了更直接地回答这个问题,您不会“扩展”特征,但您可以创建本身使用其他特征的特征。根据 PHP 手册:

trait Hello {
    public function sayHello() {
        echo 'Hello ';
    }
}

trait World {
    public function sayWorld() {
        echo 'World!';
    }
}

trait HelloWorld {
    use Hello, World;
}

class MyHelloWorld {
    use HelloWorld;
}

您可以认为这是一种在逻辑组中维护您的特征并引入一些模块化的方法。

编辑:看过一些评论后,我认为值得注意的是,在基类中使用特征也意味着特征在任何扩展它的类中,并且特征的功能优先于基类。将它放在子类中只会使特征的功能对父/基类不可用。

Parent > Trait > Child

http://php.net/manual/en/language.oop5.traits.php

于 2012-04-07T17:46:54.147 回答
32

您可以在某种程度上扩展特征。扩展 mrlee 的答案,当你use有一个特征时,你可以重命名它的方法。

例如,假设您有一个由您的框架定义的“父”特征:

trait FrameworkTrait {
    public function keepMe() {
        // Framework's logic that you want to keep
    }

    public function replaceMe() {
        // Framework's logic that you need to overwrite
    }
}

只需拉入父特征,将其replaceMe方法重命名为其他名称,然后定义您自己的replaceMe方法。

trait MyTrait {
    use FrameworkTrait {
        FrameworkTrait::replaceMe as frameworkReplaceMe;
    }

    public function replaceMe() {
        // You can even call the "parent" method if you'd like:
        $this->frameworkReplaceMe();

        // Your logic here
    }
}

然后在你的课上:

class MyClass {
    use MyTrait;
}

现在这个类的对象可以这样做:

$obj = new MyClass();

$obj->keepMe();             // calls "parent" trait
$obj->replaceMe();          // calls "child" trait
$obj->frameworkReplaceMe(); // calls "parent" trait
于 2016-06-07T19:01:18.600 回答
6

只有类可以扩展。特征不是类。它们可以被类使用/包含,但它们本身不是类。如果您认为需要扩展特征,那么它可能应该是一个类,可能是一个抽象类,而不是一个特征。

于 2012-04-07T17:08:21.407 回答