为什么在PHP中不允许用类扩展Traits?
例如:
Trait T { }
Class C use T {}
/* or */
Class C extends T {}
这种语法是否存在潜在的冲突?我认为没有。
根据PHP手册:
Traits是一种在单继承语言(如PHP)中用于代码重用的机制。Trait旨在通过使开发人员能够在不同类层次结构中自由地重复使用一组方法,从而减少单继承的某些限制。 Traits和类的组合语义被定义为一种降低复杂性并避免与多重继承和Mixins相关的典型问题的方式。
如果您想扩展一个trait,则它应该成为一个类。 如果您有一组方法在一个类中,您想在其他类中使用它们,但感觉将该类扩展(例如class Animal extends Vehicle
)不合适,则在PHP 5.4中,将其作为trait可能很好地解决问题。
更直接回答这个问题,你不能“扩展”一个trait,但你可以创建使用其他traits的traits。根据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
您可以在一定程度上扩展特征。进一步解释mrlee的回答,当您 use
一个 trait 时,您可以重命名其方法。
比如说,您有一个由框架定义的“父” trait:
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
只有类可以被继承。特质并不是类,尽管它们可以被类使用或包含,但它们本身不是类。如果您认为一个特质需要被继承,那么它可能应该是一个类,可能是一个抽象类,而不是一个特质。
protected
的函数需要进行小修复怎么办?我不想改变 Laravel 的代码,所以最好有一种方法来覆盖这个受保护的函数,使其在我的自定义 trait 中生效。更具体地说,问题出在一个硬编码的文本字符串上,我希望能够将其本地化。 - JustAMartin
Class C use T {}
除了略有不同的语法以外,与我们已经拥有的有何不同之处? - JonClass C extends Base {use T}
。 - hakre