场景:
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
Run Code Online (Sandbox Code Playgroud)
这段代码不起作用,我找不到像继承那样调用特征函数的方法.我试着打电话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);
}
}
Run Code Online (Sandbox Code Playgroud)
什么都行不通.
有没有办法使它工作或必须完全覆盖比这复杂得多的特征函数:)
irc*_*ell 600
你的最后一个几乎就在那里:
trait A {
function calc($v) {
return $v+1;
}
}
class MyClass {
use A {
calc as protected traitcalc;
}
function calc($v) {
$v++;
return $this->traitcalc($v);
}
}
Run Code Online (Sandbox Code Playgroud)
特质不是一个阶级.您无法直接访问其成员.它基本上只是自动复制和粘贴......
Yeh*_*sef 11
如果类直接实现该方法,则不会使用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
Run Code Online (Sandbox Code Playgroud)
因为子类没有直接实现该方法,所以如果否则使用父类的那些,它们将首先使用该特征.
如果你愿意,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)
Run Code Online (Sandbox Code Playgroud)
您还可以提供覆盖的方法,但仍然可以按如下方式访问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
Run Code Online (Sandbox Code Playgroud)
您可以在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);
}
}
Run Code Online (Sandbox Code Playgroud)
使用另一个特征:
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
Run Code Online (Sandbox Code Playgroud)
另一种变体:在特征中定义两个函数,一个执行实际任务的受保护函数,以及一个依次调用受保护函数的公共函数。
如果类想要覆盖该函数,这只会使类不必混乱“use”语句,因为它们仍然可以在内部调用受保护的函数。
trait A {
protected function traitcalc($v) {
return $v+1;
}
function calc($v) {
return $this->traitcalc($v);
}
}
class MyClass {
use A;
function calc($v) {
$v++;
return $this->traitcalc($v);
}
}
class MyOtherClass {
use A;
}
print (new MyClass())->calc(2); // will print 4
print (new MyOtherClass())->calc(2); // will print 3
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
87574 次 |
最近记录: |