PHP 特征方法冲突:特征“继承”和特征层次结构

2022-08-30 16:10:56

更新:我并不是唯一一个思考这个问题的人,似乎它确实是一个错误。请参阅此处。它被修复的那一天将是一个梦幻般的一天!:)


这开始是,现在它已经变成了一个.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;
}

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

致命错误:尚未应用 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;
       }
    }
    

    use TheErrorOfYourWays as Erroneous1;
    trait SpectacularStuff1 {
        use Erroneous1{
            Erroneous1::booboo as booboo1;
        }
    }
    
    use TheErrorOfYourWays as Erroneous2;
    trait SpectacularStuff2 {
        use Erroneous2{
            Erroneous2::booboo as booboo2;
        }
    }
    

我理解:

  1. 我可以将 TheErrorOfYourWays 更改为一个类,并使 booboo() 保持静态,但我想了解这种特定的特质行为。
  2. 我可以从特征中删除TheErrorOfYourWays并在类中使用它,但这几乎不是“自包含的”。每次我使用这些特征时,我都必须记住在课堂上使用TheErrorOfYourWays,即使我不直接从类中调用booboo()。听起来很危险。
  3. 我可能犯了一些新手语法错误,或者未能在深刻的层面上理解别名。如果是这样,请...解释。。。慢慢。。。
  4. 可能有更好的方法来做到这一点。如果是这样,请...解释。。。慢慢。。。
  5. 我可能过早地热情,PHP还没有这样做。让我轻轻地放下。

谢谢!


答案 1

您需要使用关键字而不是来解决 Traits 中的冲突。

Source

重写您的

class DoSomethingSpectacular {
   use SpectacularStuff1, SpectacularStuff2 {
      /* Tried separately, but included here for brevity's sake */
      SpectacularStuff1::booboo as booboo3;
      SpectacularStuff2::booboo as booboo4;
   }
}

class DoSomethingSpectacular {
    use SpectacularStuff1, SpectacularStuff2 
    {
     SpectacularStuff1::booboo insteadof SpectacularStuff2;
     SpectacularStuff2::booboo insteadof SpectacularStuff1;
    }
}

将解决冲突。


答案 2

因此,非官方的“官方”答案是:

您可以在没有别名的情况下执行此操作,而不是任何东西!但还没有...

我从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

是的,是的,你也可以用一个班级来做到这一点,但上个赛季的班级是如此


推荐