具有冲突方法名称的特征 - 如何使用?

traits with colliding method names - how to work with?

我有一个 interface 本质上定义了 getEscapedString() 它是在几个不同的特征中实现的;实际 classes 选择其中之一。这看起来类似于(请原谅打字错误,因为这只是一个例子,而不是 c/p);类似于 Layout_B、Layout_C 等

trait Layout_A {
  abstract protected function getUnescapedString() : String;
  protected function getCSS() : ?String {
    return NULL;
  }
  public function getEscapedString() : String {
    echo sprintf('<td class="%s">%s</td>', $this->getCSS(), $this->getUnescapedString());
  }
}

工作正常。不同的布局使用不同的抽象方法(而不是靠运气),但大多数实现getCSS()。一些 classes 覆盖它以实现他们自己的风格;但是,此方法不是接口的一部分,因为没有它实现也可以完美地存在。

现在需要将这些特征中的两个组合成一个 class(通过连接输出):

class DoubleOutput {
  use Layout_A, Layout_B {
    Layout_A::getEscapedString as getEscapedString_Layout_A;
    Layout_B::getEscapedString as getEscapedString_Layout_B;
  }

  public function getEscapedString() : String {
    echo getEscapedString_Layout_A();
    echo getEscapedString_Layout_B();
  }
}

这会导致 getCSS() 发生冲突,我可以解决这个问题,例如通过将其添加到使用子句中:

    Layout_A::getCSS insteadof Layout_B::getCSS;
    Layout_A::getCSS as getCSS_Layout_A;
    Layout_B::getCSS as getCSS_Layout_B;

现在结果运行良好 除了 这两个特征都访问 Layout_A::getCSS 或者 - 如果我覆盖 class 中的方法 - 这两个特征都访问新的实施。

有什么(好的)方法可以让$trait::getEscapedString()使用匹配的$traig::getCSS()方法吗?到目前为止我能想到的唯一方法是将特征更改为:

trait Layout_A {
  abstract protected function getUnescapedString() : String;
  protected function getCSS_Layout_A() : ?String {
    return NULL;
  }
  public function getEscapedString() : String {
    echo sprintf('<td class="%s">%s</td>', $this->getCSS_Layout_A(), $this->getUnescapedString());
  }
}

但这真的不好看,而且除了双重之外,这个特征的所有用法都很混乱。

例如,您有多个 classes 及其实例

class Layout_Currency;
class Layout_SimpleImage;
...

$layout_currency = new Layout_Currency();
$layout_simpleimage = new Layout_SimpleImage();
...

与特征一样,它们中的每一个都以所需的格式输出数据。

现在如果你想用单个 class 输出 Currency + SimpleImage,你可以这样实现:

class DoubleOutput {
    public function getEscapedString(){
         global $layout_currency, $layout_simpleimage;
         $layout_currency->getEscapedString();
         $layout_simpleimage->getEscapedString();
    }
}