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

时间:2013-12-04 17:41:27

标签: php class multiple-inheritance traits

更新:我对这个问题的思考并不孤单,似乎确实是一个错误。见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. 当时看起来像个好主意。
  4. 我尝试了什么:

    1. PHP手册。
    2. Google。
    3. SO包括this question - &gt;对于这种情况,这不是正确的答案。
    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;
          }
      }
      
    6. 我理解:

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

4 个答案:

答案 0 :(得分:19)

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

将解决冲突。

答案 1 :(得分:4)

所以unofficial "official" answer是:

  

你可以做到没有别名,替代或任何东西!但还没有......

我从5.5.1升级到5.5.6,但是'twas都是徒劳的。如果我记得,我会在修复程序可用时更新此答案。对于某种类似于解决方法的事情,有趣的是你可以直接调用特征静态函数。以下示例有效:

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

答案 2 :(得分:1)

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

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 ();
    }
}

它有效:)

答案 3 :(得分:0)

有点破解,只需将函数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() {}
}