避免特质碰撞 - use_once?

时间:2016-03-28 19:27:47

标签: php inheritance multiple-inheritance

我有两个PHP特征,每个特征都继承自相同的第三特征:

trait C {
    public function smallTalk() {
        echo 'c';
    }
}

trait A {
    use C;
    public function ac() {
        echo 'a'.smallTalk();
    }
}

trait B {
    use C;
    public function bc() {
        echo 'b'.smallTalk();
    }
}

我想在课堂上使用它们:

class D {
    use A, B;
    public function acbc() {
        echo ac().bc();
    }
}

但我一直收到错误

  

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

我知道use_once不是一件事,但我正在寻找与require_onceinclude_once提供的功能相同的功能,但是我需要提供相同的功能。这个例子很简单。我的真实C有很多方法,并且被2个以上的特征所遗传,所以每次使用1个以上时我都不想重复长insteadof个字符串这些特质。

2 个答案:

答案 0 :(得分:1)

您需要阅读:Conflict Resolution

  

如果两个Traits插入一个名称相同的方法,则会出现致命错误   如果冲突没有明确解决,就会产生。

     

要解决同一类中使用的Traits之间的命名冲突,请执行以下操作:   需要使用而不是运算符来选择其中一个   矛盾的方法。

     

由于这只允许排除方法,因此 as 运算符可以   过去允许包含一个冲突的方法   另一个名字。

示例:

<?php
trait A {
    public function smallTalk() {
        echo 'a';
    }
    public function bigTalk() {
        echo 'A';
    }
}

trait B {
    public function smallTalk() {
        echo 'b';
    }
    public function bigTalk() {
        echo 'B';
    }
}

class Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
    }
}

class Aliased_Talker {
    use A, B {
        B::smallTalk insteadof A;
        A::bigTalk insteadof B;
        B::bigTalk as talk;
    }
}

答案 1 :(得分:0)

这是避免编写大量代码的一种方法。基本上是利用匿名类并调用本质上来自trait C的public函数。

这仍然取决于代码的实际结构(例如,您是否使用$this):

trait C
{
    public function smallTalk()
    {
        return 'c';
    }
}

trait A
{
    public function ac()
    {
        // anonymous class to avoid leaking all Trait C functions to
        // the classes that didn't sign up for that. Can't see other bad
        // side effects except for being inefficient
        $local_class = new class {
            use C;
        };
        return 'a' . (new $local_class())->smallTalk();
    }
}

trait B
{
    public function bc()
    {
        $local_class = new class {
            use C;
        };
        return 'b' . (new $local_class())->smallTalk();
    }
}

因此您现在可以同时包含两个特征:

class D
{
    use A, B;
    public function acbc()
    {
        echo $this->ac() . $this->bc();
    }
}