php 如何覆盖特征函数并从覆盖的函数中调用它?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11939166/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to override trait function and call it from the overridden function?
提问by Shu
Scenario:
设想:
trait A {
function calc($v) {
return $v+1;
}
}
class MyClass {
use A;
function calc($v) {
$v++;
return A::calc($v);
}
}
print (new MyClass())->calc(2); // should print 4
This code doesn't work, and I cannot find a way to call a trait function like it was inherited. I tried calling self::calc($v), static::calc($v), parent::calc($v), A::calc($v)and the following:
这段代码不起作用,我找不到像继承那样调用特征函数的方法。我打过电话self::calc($v),static::calc($v),parent::calc($v),A::calc($v)和以下内容:
trait A {
function calc($v) {
return $v+1;
}
}
class MyClass {
use A {
calc as traitcalc;
}
function calc($v) {
$v++;
return traitcalc($v);
}
}
Nothing works.
什么都行不通。
Is there a way to make it work or must I override completely the trait function which is much more complex than this :)
有没有办法让它工作,或者我必须完全覆盖比这复杂得多的特征函数:)
回答by ircmaxell
Your last one was almost there:
你的最后一个几乎就在那里:
trait A {
function calc($v) {
return $v+1;
}
}
class MyClass {
use A {
calc as protected traitcalc;
}
function calc($v) {
$v++;
return $this->traitcalc($v);
}
}
The trait is not a class. You can't access its members directly. It's basically just automated copy and paste...
特征不是一个类。您无法直接访问其成员。它基本上只是自动复制和粘贴...
回答by Yehosef
If the class implements the method directly, it will not use the traits version. Perhaps what you are thinking of is:
如果该类直接实现该方法,则不会使用traits 版本。也许你在想的是:
trait A {
function calc($v) {
return $v+1;
}
}
class MyClass {
function calc($v) {
return $v+2;
}
}
class MyChildClass extends MyClass{
}
class MyTraitChildClass extends MyClass{
use A;
}
print (new MyChildClass())->calc(2); // will print 4
print (new MyTraitChildClass())->calc(2); // will print 3
Because the child classes do not implement the method directly, they will first use that of the trait if there otherwise use that of the parent class.
因为子类不直接实现该方法,如果否则使用父类的特性,它们将首先使用特性的特性。
If you want, the trait can use method in the parent class (assuming you know the method would be there) e.g.
如果你愿意,特征可以在父类中使用方法(假设你知道方法会在那里)例如
trait A {
function calc($v) {
return parent::calc($v*3);
}
}
// .... other code from above
print (new MyTraitChildClass())->calc(2); // will print 8 (2*3 + 2)
You can also provide for ways to override, but still access the trait method as follows:
您还可以提供覆盖的方法,但仍然可以访问 trait 方法,如下所示:
trait A {
function trait_calc($v) {
return $v*3;
}
}
class MyClass {
function calc($v) {
return $v+2;
}
}
class MyTraitChildClass extends MyClass{
use A {
A::trait_calc as calc;
}
}
class MySecondTraitChildClass extends MyClass{
use A {
A::trait_calc as calc;
}
public function calc($v) {
return $this->trait_calc($v)+.5;
}
}
print (new MyTraitChildClass())->calc(2); // will print 6
echo "\n";
print (new MySecondTraitChildClass())->calc(2); // will print 6.5
You can see it work at http://sandbox.onlinephpfunctions.com/code/e53f6e8f9834aea5e038aec4766ac7e1c19cc2b5
你可以在http://sandbox.onlinephpfunctions.com/code/e53f6e8f9834aea5e038aec4766ac7e1c19cc2b5看到它的工作
回答by Kartik V
An alternative approach if interested - with an extra intermediate class to use the normal OOO way. This simplifies the usage with parent::methodname
如果有兴趣,另一种方法 - 使用额外的中间类来使用正常的 OOO 方式。这简化了parent::methodname的使用
trait A {
function calc($v) {
return $v+1;
}
}
// an intermediate class that just uses the trait
class IntClass {
use A;
}
// an extended class from IntClass
class MyClass extends IntClass {
function calc($v) {
$v++;
return parent::calc($v);
}
}
回答by tarkhov
Using another trait:
使用另一个特征:
trait ATrait {
function calc($v) {
return $v+1;
}
}
class A {
use ATrait;
}
trait BTrait {
function calc($v) {
$v++;
return parent::calc($v);
}
}
class B extends A {
use BTrait;
}
print (new B())->calc(2); // should print 4

