如何覆盖trait函数并从覆盖的函数调用它?

场景:

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 

此代码不起作用,我找不到像inheritance的方式调用trait函数的方法。 我试着调用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); } } 

没有任何工作

有没有办法让它工作,或者我必须完全覆盖特征函数,这是比这更复杂:)

你最后一个几乎在那里:

 trait A { function calc($v) { return $v+1; } } class MyClass { use A { calc as protected traitcalc; } function calc($v) { $v++; return $this->traitcalc($v); } } 

这个特质不是一个阶级。 您无法直接访问其成员。 这基本上只是自动复制和粘贴…

如果类直接实现该方法,则不会使用特性版本。 也许你在想的是:

 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 

因为子类不直接实现方法,所以如果使用父类的话,他们将首先使用这个特性。

如果你想的话,特质可以在父类中使用方法(假设你知道方法将在那里),例如

 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) 

您也可以提供重写的方法,但仍然可以按如下方式访问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 

你可以在http://sandbox.onlinephpfunctions.com/code/e53f6e8f9834aea5e038aec4766ac7e1c19cc2b5看到它的工作;

如果感兴趣的话,另一种方法是用额外的中级课程来使用正常的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); } } 

使用另一个特征:

 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