【问题标题】:PHP trait method conflicts: trait "inheritance" and trait hierarchiesPHP 特征方法冲突:特征“继承”和特征层次结构
【发布时间】:2013-12-21 08:13:58
【问题描述】:

更新:我并不孤单地思考这个问题,看来这确实是一个错误。见here。修复的那一天将是美好的一天! :)


最初是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;
}

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

致命错误:尚未应用特征方法 booboo,因为与 DoSomethingSpectacular 上的其他特征方法发生冲突。

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

我为什么要这样做:

  1. 我想创建 自包含 特征和类(混搭风格)。 如果可能的话,我想说“使用”,然后神奇的事情必须发生。不必摸不着头脑去想,“现在那个特性又出现在什么命名空间中了?”等等等等。
  2. 当我做一些“冒险”的事情并发现我无意中造成了冲突时,无需即时编辑类和特征。
  3. 当时似乎是个好主意。

我尝试过的:

  1. PHP 手册。
  2. 谷歌。
  3. 所以包括this question -> 不是这种情况的正确答案。
  4. Found this 但我使用的是 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() 设为静态,但我想了解这个特定的 trait 行为。
  2. 我可以从特征中删除 TheErrorOfYourWays 并在类中使用它,但这几乎不是“独立的”。每次我使用这些特征时,我都必须记住在课堂上使用 TheErrorOfYourWays,即使我没有直接从课堂上调用 booboo()。听起来很危险。
  3. 我可能犯了一些新手语法错误,或者无法深入理解别名。如果是这样,请......解释......慢慢......
  4. 可能有更好的方法来做到这一点。如果是这样,请......解释......慢慢......
  5. 我可能过早地热情,PHP 还没有做到这一点。让我轻轻放下。

谢谢!

【问题讨论】:

    标签: php class multiple-inheritance traits


    【解决方案1】:

    您需要使用关键字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;
       }
    }
    

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

    将解决冲突。

    【讨论】:

    • 如问题中所述,我做到了,但这也产生了错误。请提供一个工作代码示例,因为可能是我没有正确实现它。谢谢:)
    • 嗯...嗯,谢谢你教我正确使用代替。我不知道 :)。但这仍然不能解决特质层面的冲突。它要求我知道哪些特征和类调用相同的特征,并且可能导致很长的替代列表。还是我还缺少什么?
    • 我认为事情就是这样(你需要一个很长的列表:(),顺便说一句,你有没有看过我提供的链接的example #5 : conflict resolution。?
    • 我确实看到了 #5 并且我尝试了它,但它没有给我想要的结果。我来这里之前仔细阅读了手册,相信我;)这个“长名单”消息让我感到难过:(。
    • 非常感谢 :) 非常感谢您的帮助!
    【解决方案2】:

    所以unofficial "official" answer 是:

    您可以在没有别名的情况下做到这一点,而不是或任何东西!但还没有……

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

    是的,是的,你也可以通过课程来做到这一点,但课程是soooo上一季。

    【讨论】:

      【解决方案3】:

      我找到了另一种临时解决此问题的方法:

      trait A {
         public function foo(){
             echo 'foo';
         }
      }
      
      trait B {
         public function foofoo(){
             return $this->foo () . 'foo';
         }
      }
      
      trait C {
         public function foobar(){
             return $this->foo () . 'bar';
         }
      }
      
      class DoSomethingSpectacular {
          use A, B, C;
      
          public function foobarfoofoo () {
              echo $this->foobar () . $this->foofoo ();
          }
      }
      

      它有效:)

      【讨论】:

      • 有趣...只需要记住始终使用 A ;-)
      【解决方案4】:

      小技巧,只需将函数 booboo 添加到类 DoSomethingSpectacular

      <?php
      trait TheErrorOfYourWays{
      
         public function booboo(){
             echo 'You had a booboo :(';
         }
      }
      
      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;
         }
      
        //very ugly hack
        public function booboo() {}
      }
      

      【讨论】:

        猜你喜欢
        • 2016-08-20
        • 2020-11-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多