与其他性状方法的碰撞

2022-08-30 10:52:38

我如何处理同名方法的特征?

trait FooTrait {
  public function fooMethod() {
        return 'foo method';
  }

  public function getRow() {
        return 'foo row';
  }
}

trait TooTrait {
    public function tooMethod() {
        return 'too method';
    }

    public function getRow() {
        return 'too row';
    }
}

class Boo
{
    use FooTrait;
    use TooTrait;

    public function booMethod() {
        return $this->fooMethod();
    }
}

错误

致命错误:尚未应用 Trait 方法 getRow,因为在 Boo 上与其他特质方法发生冲突...

我该怎么办?

而且,使用两个相同的方法名称,我如何从中获取该方法?trait FooTrait

$a = new Boo;
var_dump($a->getRow()); // Fatal error: Call to undefined method Boo::getRow() in... 

编辑:

class Boo
{
    use FooTrait, TooTrait {
        FooTrait::getRow insteadof TooTrait;
    }

    public function booMethod() {
        return $this->fooMethod();
    }
}

如果我也想从via获取方法怎么办?可能吗?getRowTooTraitBoo


答案 1

关于冲突的 PHP 文档:

如果两个 Traits 插入具有相同名称的方法,如果未显式解决冲突,则会生成致命错误。

若要解决同一类中使用的特征之间的命名冲突,需要使用 insteadof 运算符来准确选择一个冲突的方法。

由于这只允许排除方法,因此 as 运算符可用于允许在另一个名称下包含其中一个冲突的方法。

示例 #5 冲突解决

在此示例中,Talker 使用特征 A 和 B。由于 A 和 B 具有冲突的方法,因此它定义了使用来自 trait B 的 smallTalk 变体,以及来自 trait A 的 bigTalk 变体。

Aliased_Talker利用 as 运算符,能够在额外的别名对话下使用 B 的 bigTalk 实现。

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

因此,在您的情况下,它可能是

class Boo {
    use FooTrait, TooTrait {
        FooTrait::getRow insteadof TooTrait;
    }

    public function booMethod() {
        return $this->fooMethod();
    }
}

(即使你单独使用,它也可以工作,但我认为它更清晰)

或者使用 来声明别名。as


答案 2

是的,这是可能的,你可以使用这样的东西(编辑内容的答案):

class Boo {
    use FooTrait, TooTrait {
        FooTrait::getRow as getFooRow;
        TooTrait::getRow as getTooRow;
    }

    public function getRow(... $arguments)
    {
         return [ 'foo' => $this->getFooRow(... $arguments), 'too' => $this->getTooRow(... $arguments) ];
    }

    public function booMethod(... $arguments)
    {
        return $this->getFooRow(... $arguments);
    }
}

推荐