与其他 trait 方法的冲突

Posted

技术标签:

【中文标题】与其他 trait 方法的冲突【英文标题】:Collisions with other trait methods 【发布时间】:2014-09-23 17:26:45 【问题描述】:

如何处理具有同名方法的特征?

trait FooTrait 
  public function fooMethod() 
        return 'foo method';
  

  public function getRow() 
        return 'foo row';
  


trait TooTrait 
    public function tooMethod() 
        return 'too method';
    

    public function getRow() 
        return 'too row';
    


class Boo

    use FooTrait;
    use TooTrait;

    public function booMethod() 
        return $this->fooMethod();
    

错误,

致命错误:尚未应用特征方法 getRow,因为存在 与 Boo 上的其他 trait 方法发生冲突...

我该怎么办?

另外,如果有两个相同的方法名,我如何获取来自trait FooTrait的方法?

$a = new Boo;
var_dump($a->getRow()); // Fatal error: Call to undefined method Boo::getRow() in... 

编辑:

class Boo

    use FooTrait, TooTrait 
        FooTrait::getRow insteadof TooTrait;
    

    public function booMethod() 
        return $this->fooMethod();
    

如果我也想通过BooTooTrait 获取方法getRow 怎么办?有可能吗?

【问题讨论】:

【参考方案1】:

关于冲突的 php 文档:

如果两个 Traits 插入同名的方法,则发生致命错误 产生,如果冲突没有明确解决。

为了解决同一类中使用的 Traits 之间的命名冲突, 需要使用而不是运算符来准确选择其中一个 冲突的方法。

由于这仅允许排除方法,因此 as 运算符可以 用于允许包含以下冲突方法之一 另一个名字。

示例 #5 冲突解决

在这个例子中,Talker 使用特征 A 和 B。因为 A 和 B 有 冲突的方法,它定义使用 smallTalk 的变体 trait B,以及来自 trait A 的 bigTalk 的变体。

Aliased_Talker 使用 as 操作符来使用 B 的 bigTalk 实现在一个额外的别名 talk 下。

<?php
trait A 
    public function smallTalk() 
        echo 'a';
    

    public function bigTalk() 
        echo 'A';
    


trait B 
    public function smallTalk() 
        echo 'b';
    

    public function bigTalk() 
        echo 'B';
    


class Talker 
    use A, B 
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
    


class Aliased_Talker 
    use A, B 
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
        B::bigTalk as talk;
    

所以在你的情况下它可能是

class Boo 
    use FooTrait, TooTrait 
        FooTrait::getRow insteadof TooTrait;
    

    public function booMethod() 
        return $this->fooMethod();
    

即使你分开use也可以,但我认为它更清楚

或者使用as 声明一个别名。

【讨论】:

感谢您的回答!请问-如果我也想通过BooTooTrait 获取方法getRow 怎么办?有可能吗? 声明一个别名。 TooTrait::getRow as getRowOfToo;试试 也是这样破解的。在我看来,当前的行为不是预期的行为。我还期望将“as”传递给 using 类。 请注意,令人惊讶的是,当类中的方法与该类中使用的特征中的同名方法冲突时,即使该特征的方法不可访问,您也不会收到致命错误.【参考方案2】:

是的,你可以使用这样的东西(编辑内容的答案):

class Boo 
    use FooTrait, TooTrait 
        FooTrait::getRow as getFooRow;
        TooTrait::getRow as getTooRow;
    

    public function getRow(... $arguments)
    
         return [ 'foo' => $this->getFooRow(... $arguments), 'too' => $this->getTooRow(... $arguments) ];
    

    public function booMethod(... $arguments)
    
        return $this->getFooRow(... $arguments);
    

【讨论】:

以上是关于与其他 trait 方法的冲突的主要内容,如果未能解决你的问题,请参考以下文章

std type_traits 与 Qt type_traits 冲突

php trait

scala中trait学习笔记

Mixins 与 Traits

trait优先级 与 使用

Rust 中 trait 的冲突实现