为什么我们不允许在PHP中使用类扩展Traits?
例如:
Trait T { }
Class C use T {}
/* or */
Class C extends T {}
此类语法是否存在潜在冲突?我不这么认为。
答案 0 :(得分:36)
PHP手册如下:
Traits是一种在单继承语言(如PHP)中重用代码的机制。 Trait旨在通过使开发人员能够在生活在不同类层次结构中的多个独立类中自由地重用方法集来减少单继承的某些限制。 Traits和类组合的语义以降低复杂性的方式定义,并避免了与多重继承和Mixins相关的典型问题。
如果你想扩展一个特性,那么它应该是一个类。如果你想在一个类中使用一组你想要在其他类中使用的方法,但是扩展类是不合适的(例如class Animal extends Vehicle
),那么在PHP 5.4中它可以很好地作为特征。
要更直接地回答这个问题,你不要'延伸'一个特征,但你可以创建自己使用其他特征的特征。根据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
答案 1 :(得分:17)
你可以稍微扩展一下特征。扩展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
答案 2 :(得分:5)
只能扩展课程。特征是不是类。它们可以由类使用/包含,但不是类本身。如果你认为某个特征需要扩展,那么它可能应该是一个类,可能是一个抽象的类,而不是一个特征。