为什么方法重命名在PHP特征中不起作用?

时间:2017-05-07 20:10:28

标签: php traits

我使用PHP 7.1.0。

假设我们有一个特征,我们在一个类中使用它并重命名导入的方法:

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

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

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

为什么PHP仍然允许我使用旧的方法名称(在这种情况下为A)?

这真的很痛苦,因为在更复杂的示例中,您不能依赖于方法重命名 - 因此您可能会意外地收到“不兼容的声明”错误:

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

我认为,这段代码应该可行。自从我在init()类中将initBase()重命名为Base并在BaseTrait内使用MainTrait时进行了相同的重命名,我希望这种方法({{1} }})不会与BaseTrait::init()发生冲突。事实上,PHP说我有不兼容的声明。其背后的原因是重命名MainTrait::init()不起作用 - 方法init as initBase仍在我的init类中!

如果不从一开始就将BaseTrait :: init()重命名为BaseTrait :: initBase()(而不仅仅是Base语句),有没有办法解决这个问题?

我应该将此视为PHP错误并报告吗?这种行为背后有什么合理的吗?

1 个答案:

答案 0 :(得分:0)

正如评论中所述和完整性;来自PHP manual section on Traits

  

Aliased_Talker使用as运算符可以使用   B的bigTalk实施另外的别名谈话。

然后:

  

as运算符可用于为其中一个方法添加别名。   请注意,as运算符不会重命名该方法,也不会影响该方法   任何其他方法。

因此as添加了别名,但不会以任何方式替换或影响原始方法。这是预期的行为。