PHP特征方法冲突:特质"继承"和特征层次结构

Jus*_*igh 24 php class multiple-inheritance traits

更新:在我对这个问题的思考中并不孤单,这似乎确实是一个错误.看到这里.它修复的那一天将是一个美好的一天!:)


这开始了I love PHP traits! I'm going to use them everywhere! ^_^,现在它变成了一个Thought Exercise / Learning Experience >_<.

请考虑以下示例:

trait TheErrorOfYourWays{

   public function booboo(){
       echo 'You had a booboo :(';
   }
}

trait SpectacularStuff1 {
    use TheErrorOfYourWays; 
}

trait SpectacularStuff2 {
    use TheErrorOfYourWays;
}

class DoSomethingSpectacular {
    use SpectacularStuff1, SpectacularStuff2;
}
Run Code Online (Sandbox Code Playgroud)

这导致(显然不那么明显):

致命错误:Trait方法booboo尚未应用,因为在DoSomethingSpectacular上存在与其他特征方法的碰撞.

所以我的问题是:如何解决特征中的方法冲突?是否有可能实现重叠特质"继承"?如果是这样,那么"正确"的方法是什么?

为什么我要这样做:

  1. 我想创建自包含的特征和类(混合和匹配样式).如果可能的话,我想说"使用"然后必须发生神奇的东西.没有必要抓住我的想法,"现在又有什么命名空间?"等等等等.
  2. 当我做一些"冒险"的事情并发现我无意中造成了冲突时,不必动态编辑类和特征.
  3. 当时看起来像个好主意.

我尝试过的:

  1. PHP手册.
  2. 谷歌.
  3. 所以包括这个问题 - >这个场景的答案不正确.
  4. 发现这个,但我使用的是PHP 5.5.1版.这是固定的,对吗?对?
  5. 一系列奇妙的"as",别名,甚至是不同的地方,时代,宇宙等.包括但不限于:

    trait SpectacularStuff1 {
       use TheErrorOfYourWays{
          TheErrorOfYourWays::booboo as booboo1;
       }
    }
    trait SpectacularStuff2 {
       use TheErrorOfYourWays{
          TheErrorOfYourWays::booboo as booboo2;
       }
    }
    class DoSomethingSpectacular {
       use SpectacularStuff1, SpectacularStuff2 {
          /* Tried separately, but included here for brevity's sake */
          SpectacularStuff1::booboo as booboo3;
          SpectacularStuff2::booboo as booboo4;
       }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    use TheErrorOfYourWays as Erroneous1;
    trait SpectacularStuff1 {
        use Erroneous1{
            Erroneous1::booboo as booboo1;
        }
    }
    
    use TheErrorOfYourWays as Erroneous2;
    trait SpectacularStuff2 {
        use Erroneous2{
            Erroneous2::booboo as booboo2;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

我明白那个:

  1. 我可以将TheErrorOfYourWays更改为一个类并使booboo()静态,但我想了解这个特定的特征行为.
  2. 我可以从特征中删除TheErrorOfYourWays并在类中使用它,但那时几乎不是"自包含"的.每次我使用这些特性时我都要记得在类中使用TheErrorOfYourWays,即使我没有直接从类中调用booboo().听起来很危险.
  3. 我可能已经做了一些新手语法错误或者未能在深层次上理解别名.如果是的话,请......解释......慢慢......
  4. 可能有更好的方法来做到这一点.如果是的话,请......解释......慢慢......
  5. 我可能过早热情,PHP还没有做到这一点.让我温柔地说.

谢谢!

Sha*_*ran 20

您需要使用关键字 insteadof来解决Traits中的冲突.

Source

重写你的

class DoSomethingSpectacular {
   use SpectacularStuff1, SpectacularStuff2 {
      /* Tried separately, but included here for brevity's sake */
      SpectacularStuff1::booboo as booboo3;
      SpectacularStuff2::booboo as booboo4;
   }
}
Run Code Online (Sandbox Code Playgroud)

class DoSomethingSpectacular {
    use SpectacularStuff1, SpectacularStuff2 
    {
     SpectacularStuff1::booboo insteadof SpectacularStuff2;
     SpectacularStuff2::booboo insteadof SpectacularStuff1;
    }
}
Run Code Online (Sandbox Code Playgroud)

将解决冲突.


Jus*_*igh 5

所以非官方的“官方”答案是:

你可以在没有别名的情况下做到这一点,而不是或任何东西!但尚未...

我从 5.5.1 升级到 5.5.6 但都是徒劳的。当修复可用时,我将更新此答案。有趣的是,您可以直接调用 trait 静态函数。以下示例有效:

trait TheErrorOfYourWays{
    public static function booboo($thisTrait){
        echo 'You had a booboo :( in '.$thisTrait.'<br>';
    }
}

trait SpectacularStuff1 {
    public function boobooTest1(){
        TheErrorOfYourWays::booboo(__TRAIT__);
    }
}

trait SpectacularStuff2 {
    public function boobooTest2(){
        TheErrorOfYourWays::booboo(__TRAIT__);
    }
}

class DoSomethingSpectacular {
    use SpectacularStuff1, SpectacularStuff2;
}

$boobooAChoo = new DoSomethingSpectacular();
$boobooAChoo->boobooTest1(); // You had a booboo :( in SpectacularStuff1
$boobooAChoo->boobooTest2(); // You had a booboo :( in SpectacularStuff2
Run Code Online (Sandbox Code Playgroud)

是的,是的,你也可以通过课程来做到这一点,但上个赛季的课程太棒了