Home > Software engineering >  traits with colliding method names - how to work with?
traits with colliding method names - how to work with?

Time:03-07

I have an interface in essence defining getEscapedString() which is implemented in a couple of different traits; the actual classes pick one of them. This looks something similar to (excuse typos as this is just an example and not c/p); similar for Layout_B, Layout_C etc.

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

Works fine. Different layout use different abstract methods (rather by fortune), but most of them implement getCSS(). Some classes overwrite this to implement their own style; however, this method is not part of the interface as an implementation can perfectly live without it.

Now there is the need to combine two of these traits into a single class (by concatenating the output):

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

This causes a collision of getCSS() which I could resolve e.g. by adding this into the use-clause:

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

Now the result runs fine except that both traits access Layout_A::getCSS or - if I overwrite the method within the class - both traits access the new implementation.

Is there any (nice) way to let $trait::getEscapedString() use the matching $traig::getCSS() method? Only way I can think of so far is to change the traits to:

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

But this is really not good-looking and rather confusing for all usages of this trait except the double one.

CodePudding user response:

For example you have serveral classes and their instances

class Layout_Currency;
class Layout_SimpleImage;
...

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

Like the traits, each of them outputs data in the desired format.

Now if you want to output Currency SimpleImage with a single class, you could implement it like this:

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