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

Posted

技术标签:

【中文标题】为啥方法重命名在 PHP 特征中不起作用?【英文标题】:Why method renaming does not work in PHP traits?为什么方法重命名在 PHP 特征中不起作用? 【发布时间】:2017-10-05 18:41:20 【问题描述】:

我使用 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;

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

有没有什么办法可以解决这个问题,而无需从一开始就将 BaseTrait::init() 重命名为 BaseTrait::initBase() 之类的东西(不仅仅是在use 语句中)?

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

【问题讨论】:

php.net 所写的内容:The Aliased_Talker makes use of the as operator to be able to use B's bigTalk implementation under an 附加 alias talk. - php.net/manual/en/language.oop5.traits.php。所以as 添加别名但不替换方法。然后: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.' @splash58 好的,谢谢。我明白了:“as”不是重命名,它只是“别名”(老实说,我在阅读关于特征的页面时没有提到这个注释)。这背后有什么原因吗?我的意思是,使用别名而不是重命名有什么好处?在我看来,这很不方便。 我认为insteadof 做你想要的。我错了吗?我不知道特质这么深 @splash58 而不是仅当您在同一类中使用 2 个特征时才有效(据我所知)。我对它进行了试验,但无法将其应用于我的情况。 当您的类中的方法与 trait 中的方法具有相同的名称时,显然需要使用别名。由于 trait 方法被类的方法覆盖,这是您通常不想要的,因此您使用别名。将方法 A 添加到您的课程并进行测试。 【参考方案1】:

如 cmets 中所述,出于完整性考虑;来自PHP manual section on Traits:

Aliased_Talker 使用 as 运算符可以使用 B 的 bigTalk 在另一个别名谈话下的实现。

然后:

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

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

【讨论】:

以上是关于为啥方法重命名在 PHP 特征中不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用命名空间在我的 C++ 项目中不起作用?

重命名文件选项在 dropzone.js 中不起作用

Apple 文件应用程序“重命名”文件/文件夹功能在文件提供程序扩展中不起作用

为啥php邮件功能在xampp中不起作用

为啥 FBLogin 在模拟器中不起作用? - 它留在 Safari 中?

为啥 Bootstrap 3 导航栏下拉菜单在 IE8 中不起作用?