Как переопределить функцию признака и вызвать ее из переопределенной функции?

Сценарий:

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 

Этот код не работает, и я не могу найти способ вызвать функцию признака, как будто она была унаследована. Я попытался вызвать 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); } } 

Ничего не работает.

Есть ли способ заставить его работать, или я должен полностью переопределить функцию признака, которая намного сложнее, чем эта 🙂

Related of "Как переопределить функцию признака и вызвать ее из переопределенной функции?"

Твой последний был почти там:

 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 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