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

本文讨论了如何在PHP中正确覆盖trait的函数并从重写后的函数内部调用trait的原始实现。帖子中提到,当类直接实现trait的方法时,不会使用trait的版本,需要通过特定的方式访问trait的成员。提供了解决方案,包括使用parent::functionName或者创建额外的中间类来实现正常的面向对象调用。此外,还提到了使用另一个trait作为替代方案。
摘要由CSDN通过智能技术生成

本文翻译自: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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值