Why we are not allowed to extend Traits with Classes in PHP?
为什么我们不允许在PHP中使用类扩展Traits?
For example:
例如:
Trait T { }
Class C use T {}
/* or */
Class C extends T {}
Is there any potential conflict for such syntax? I do not think so.
这种语法有没有潜在的冲突?我不这么认为。
3 个解决方案
#1
33
The PHP manual states thus:
PHP手册如下:
Traits is a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies. The semantics of the combination of Traits and classes is defined in a way which reduces complexity, and avoids the typical problems associated with multiple inheritance and Mixins.
Traits是一种在单继承语言(如PHP)中重用代码的机制。 Trait旨在通过使开发人员能够在生活在不同类层次结构中的多个独立类中*地重用方法集来减少单个继承的某些限制。 Traits和类组合的语义以降低复杂性的方式定义,并避免了与多重继承和Mixins相关的典型问题。
If you're looking to extend a trait, then it should probably be a class. If you have a set of methods in one class that you want to use in others, but it feels inappropriate to extend the class (eg. class Animal extends Vehicle
), then in PHP 5.4 it could work well as a trait.
如果你想扩展一个特性,那么它应该是一个类。如果你想在一个类中使用一组你想要在其他类中使用的方法,但是扩展类是不合适的(例如,类扩展Vehicle),那么在PHP 5.4中它可以很好地用作特征。
To answer the question more directly, you don't 'extend' a trait, but you can create traits which themselves use other traits. As per the PHP manual:
要更直接地回答这个问题,你不要“扩展”一个特征,但你可以创建自己使用其他特征的特征。根据PHP手册:
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World!';
}
}
trait HelloWorld {
use Hello, World;
}
class MyHelloWorld {
use HelloWorld;
}
You can consider this to be a way to maintain your traits in logical groups, and to introduce some modularity.
您可以将此视为一种在逻辑组中维护特征的方法,并引入一些模块化。
Edit: having seen some of the comments, I think it's worthwhile to note that using a trait in a base class also means that trait is in any class that extends it, and the trait's functions take precedence over the base class'. Putting it in the child class would merely make the trait's functions unavailable to the parent/base class.
编辑:看过一些评论后,我认为值得注意的是,在基类中使用特征也意味着特征在任何扩展它的类中,并且特征的功能优先于基类。将它放在子类中只会使特性的函数对父类/基类不可用。
Parent > Trait > Child
http://php.net/manual/en/language.oop5.traits.php
http://php.net/manual/en/language.oop5.traits.php
#2
12
You can extend traits somewhat. Expanding on mrlee's answer, when you use
a trait you can rename its methods.
你可以稍微扩展一下特征。扩展mrlee的答案,当你使用特征时,你可以重命名它的方法。
Say for example you have a "parent" trait that was defined by your framework:
比如说你有一个由你的框架定义的“父”特征:
trait FrameworkTrait {
public function keepMe() {
// Framework's logic that you want to keep
}
public function replaceMe() {
// Framework's logic that you need to overwrite
}
}
Simply pull in the parent trait, rename its replaceMe
method to something else, and define your own replaceMe
method.
只需拉入父特征,将其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
}
}
And then in your class:
然后在你的班上:
class MyClass {
use MyTrait;
}
Now objects of this class can do this:
现在这个类的对象可以这样做:
$obj = new MyClass();
$obj->keepMe(); // calls "parent" trait
$obj->replaceMe(); // calls "child" trait
$obj->frameworkReplaceMe(); // calls "parent" trait
#3
5
Only classes can be extended. Traits are not classes. They can be used/included by classes but are not classes themselves. If you think a trait needs to be extended then it probably should be a class, probably an abstract one, and not a trait.
只能扩展课程。特质不是阶级。它们可以由类使用/包含,但不是类本身。如果你认为某个特征需要扩展,那么它可能应该是一个类,可能是一个抽象的类,而不是一个特征。
#1
33
The PHP manual states thus:
PHP手册如下:
Traits is a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies. The semantics of the combination of Traits and classes is defined in a way which reduces complexity, and avoids the typical problems associated with multiple inheritance and Mixins.
Traits是一种在单继承语言(如PHP)中重用代码的机制。 Trait旨在通过使开发人员能够在生活在不同类层次结构中的多个独立类中*地重用方法集来减少单个继承的某些限制。 Traits和类组合的语义以降低复杂性的方式定义,并避免了与多重继承和Mixins相关的典型问题。
If you're looking to extend a trait, then it should probably be a class. If you have a set of methods in one class that you want to use in others, but it feels inappropriate to extend the class (eg. class Animal extends Vehicle
), then in PHP 5.4 it could work well as a trait.
如果你想扩展一个特性,那么它应该是一个类。如果你想在一个类中使用一组你想要在其他类中使用的方法,但是扩展类是不合适的(例如,类扩展Vehicle),那么在PHP 5.4中它可以很好地用作特征。
To answer the question more directly, you don't 'extend' a trait, but you can create traits which themselves use other traits. As per the PHP manual:
要更直接地回答这个问题,你不要“扩展”一个特征,但你可以创建自己使用其他特征的特征。根据PHP手册:
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World!';
}
}
trait HelloWorld {
use Hello, World;
}
class MyHelloWorld {
use HelloWorld;
}
You can consider this to be a way to maintain your traits in logical groups, and to introduce some modularity.
您可以将此视为一种在逻辑组中维护特征的方法,并引入一些模块化。
Edit: having seen some of the comments, I think it's worthwhile to note that using a trait in a base class also means that trait is in any class that extends it, and the trait's functions take precedence over the base class'. Putting it in the child class would merely make the trait's functions unavailable to the parent/base class.
编辑:看过一些评论后,我认为值得注意的是,在基类中使用特征也意味着特征在任何扩展它的类中,并且特征的功能优先于基类。将它放在子类中只会使特性的函数对父类/基类不可用。
Parent > Trait > Child
http://php.net/manual/en/language.oop5.traits.php
http://php.net/manual/en/language.oop5.traits.php
#2
12
You can extend traits somewhat. Expanding on mrlee's answer, when you use
a trait you can rename its methods.
你可以稍微扩展一下特征。扩展mrlee的答案,当你使用特征时,你可以重命名它的方法。
Say for example you have a "parent" trait that was defined by your framework:
比如说你有一个由你的框架定义的“父”特征:
trait FrameworkTrait {
public function keepMe() {
// Framework's logic that you want to keep
}
public function replaceMe() {
// Framework's logic that you need to overwrite
}
}
Simply pull in the parent trait, rename its replaceMe
method to something else, and define your own replaceMe
method.
只需拉入父特征,将其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
}
}
And then in your class:
然后在你的班上:
class MyClass {
use MyTrait;
}
Now objects of this class can do this:
现在这个类的对象可以这样做:
$obj = new MyClass();
$obj->keepMe(); // calls "parent" trait
$obj->replaceMe(); // calls "child" trait
$obj->frameworkReplaceMe(); // calls "parent" trait
#3
5
Only classes can be extended. Traits are not classes. They can be used/included by classes but are not classes themselves. If you think a trait needs to be extended then it probably should be a class, probably an abstract one, and not a trait.
只能扩展课程。特质不是阶级。它们可以由类使用/包含,但不是类本身。如果你认为某个特征需要扩展,那么它可能应该是一个类,可能是一个抽象的类,而不是一个特征。