Why method renaming does not work in PHP traits?

落爺英雄遲暮 提交于 2019-12-05 21:46:04

问题


I use PHP 7.1.0.

Let's say we have a trait, we use it inside a class and rename the imported method:

trait T
{
    public function A() {
        echo ".";
    }
}

class C
{
    use T {
        A as B;
    }
}

$c = new C();
$c->B();
$c->A(); // Why does it work?

Why does PHP still allow me to use old method name (A in this case)?

It's really a pain because in more complex examples you cannot rely on method renaming - and thus you can unexpectedly receive "incompatible declarations" error:

class BaseSrc
{
}

trait BaseTrait
{
    public function init(BaseSrc $baseSrc)
    {
        echo "Init Base";
    }
}

class Base
{
    use BaseTrait {
        BaseTrait::init as initBase;
    }
}

$base = new Base();
$base->initBase(new BaseSrc());
$base->init(new BaseSrc()); // WHY DOES IT WORK?????

class MainSrc extends BaseSrc
{
}

trait MainTrait
{
    use BaseTrait {
        BaseTrait::init as initBase;
    }

    public function init(MainSrc $mainSrc)
    {
        $this->initBase($mainSrc);
        echo "Init Main";
    }
}

// Warning: Declaration of MainTrait::init(MainSrc $mainSrc) should be compatible with Base::init(BaseSrc $baseSrc)
class Main extends Base
{
    use MainTrait;
}

I think, this code should work. Since I renamed init() into initBase() in the Base class AND did the same renaming when using BaseTrait inside MainTrait, I expect that this method (BaseTrait::init()) will not conflict with MainTrait::init(). In fact, PHP says that I have incompatible declarations. The reason behind it is that renaming init as initBase does not work - method init is still there, in my Base class!

Is there any way how to solve this problem without renaming BaseTrait::init() into something like BaseTrait::initBase() from the very beginning (not just in the use statement)?

Should I consider this as a PHP bug and report it? Is there anything reasonable behind this behaviour?


回答1:


As mentioned in the comments and for completeness; From the PHP manual section on Traits:

The Aliased_Talker makes use of the as operator to be able to use B's bigTalk implementation under an additional alias talk.

And then:

The as operator can be used to add an alias to one of the methods. Note the as operator does not rename the method and it does not affect any other method either.

So as adds an alias but does not replace or affect the original method in any way. This is the expected behavior.



来源:https://stackoverflow.com/questions/43836171/why-method-renaming-does-not-work-in-php-traits

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!