当前位置: 首页 > 知识库问答 >
问题:

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

杨鸿畅
2023-03-14

更新:我并不是唯一一个思考这个问题的人,它似乎确实是一个错误。看这里。这一天是固定的将是一个梦幻般的一天!:)

这是从我喜欢PHP特性开始的!我要在任何地方使用它们^_^ 思维练习/学习体验

考虑以下示例:

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,因为在dosomethingspectical上存在与其他Trait方法的冲突。

所以我的问题是:如何解决性状中的方法冲突?有没有可能实现重叠性状“遗传”?如果是这样,那么这样做的“正确”方式是什么?

我为什么要这样做:

  1. 我想创建自包含的特征和类(混合和匹配风格)。如果可能的话,我想说“使用”,然后神奇的事情一定会发生。不用挠头想,“现在这个特征又在哪个命名空间里了?”等等。
  2. 当我做一些“冒险”的事情,发现我无意中制造了冲突时,不必匆忙编辑类别和特征。
  3. 当时看起来是个好主意。

我所尝试的:

>

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. 我可以将错误方式更改为类并使booboo()成为静态的,但我想了解这种特殊的特性行为
  2. 我可以从traits中删除errorofyourways,并在课堂上使用它,但这很难做到“自给自足”。每次我使用traits时,我必须记住在类中使用errorofyourways,即使我没有直接从类中调用booboo()。听起来很危险
  3. 我可能犯了一些新手语法错误,或者未能深刻理解别名。如果是,请。。。解释慢慢地
  4. 也许有更好的方法可以做到这一点。如果是,请。。。解释慢慢地
  5. 我可能有点过早的热情,PHP还没有做到这一点。轻轻地让我下来

谢谢


共有3个答案

班浩皛
2023-03-14

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

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

它是有效的:)

尉迟宪
2023-03-14

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

你可以做到没有混淆现象,而不是任何事情!但还没有...

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

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

郏经纬
2023-03-14

您需要使用关键字代替来解决Traits中的冲突。

源代码

重写你的

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

会解决冲突。

 类似资料:
  • 我正在处理的作曲家包有问题。它实现了一个特性计费。 我试图在我的类中重写此方法 但是该方法没有被重写。作为测试,我覆盖了一些公共功能,它们运行良好,这是特征的限制吗?我试图在网上找到答案,但没有找到。 我试图重写这个函数,因为我需要自定义BraintreeSubcript类的行为。 任何帮助都将不胜感激。

  • SQLAlchemy支持三种继承形式: 单表继承 ,其中几种类型的类由一个表表示, 具体的表继承 ,其中每种类型的类都由独立的表表示,并且 联接表继承 ,其中类层次结构在依赖表中被分解,每个类都由其自己的表表示,该表只包含该类的本地属性。 最常见的继承形式是单表和联接表,而具体的继承则面临更多的配置挑战。 在继承关系中配置映射器时,SQLAlchemy可以加载元素 polymorphically

  • 我有两种方法的特点。实现此特性的某些结构(但不是所有结构)对其中一种方法具有相同的实现: 该示例中有三个结构,每个结构都实现了trait,其中两个结构以完全相同的方式实现了方法。 有没有办法让他们共享该函数的代码? 我想到了第二个特性,它继承自,并提供作为该特性的默认实现,如下所示: 这不起作用,因为Rust中的特征继承意味着两个特征都需要实现,因此它不会让我在的和实现中键入相同的代码。

  • 问题内容: 我有两个平行的继承链: 我的经验是,并行继承层次结构在增长时会成为维护上的麻烦。 即不添加方法到我的主要类。 如何避免并行继承层次结构而又不破坏关注点分离的概念? 问题答案: 我正在考虑使用“访客”模式。 这样,您就可以避免多余的继承树,并使格式化逻辑与Vehicle类分开。当然,当您创建新的载具时,您必须向Formatter接口添加另一种方法(并在Formatter接口的所有实现中实

  • 当使用“joined”、“single”或“concrete”表继承样式在继承层次结构中映射类时,如中所述 映射类继承层次结构 通常的行为是,对特定基类的查询也将生成与子类相对应的对象。当单个查询能够返回每个结果行具有不同类或子类的结果时,我们使用术语“多态加载”。 在多态加载领域,特别是联合表继承和单表继承,还有一个额外的问题,子类属性需要预先查询,然后再加载。当预先查询某个特定子类的属性时,我