本文翻译自:How to override trait function and call it from the overridden function?
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 :) 有没有办法使它工作或必须完全覆盖比这复杂得多的特征函数:)
#1楼
参考:https://stackoom.com/question/o5vC/如何覆盖trait函数并从重写函数调用它
#2楼
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... 它基本上只是自动复制和粘贴......
#3楼
If the class implements the method directly, it will not use the traits version. 如果类直接实现该方法,则不会使用traits版本。 Perhaps what you are thinking of is: 也许你在想的是:
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) eg 如果你愿意,trait可以在父类中使用方法(假设你知道方法会在那里),例如
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上看到它的工作原理
#4楼
An alternative approach if interested - with an extra intermediate class to use the normal OOO way. 如果感兴趣的另一种方法 - 使用额外的中间类来使用普通的OOO方式。 This simplifies the usage with parent::methodname 这简化了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);
}
}
#5楼
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