28 July 2011
PHP will introduce traits in 5.4. While testing this feature with 5.4.0alpha2 I was wondering how it deals with the well known diamond problem.
trait T1 {
public function f1() { echo __METHOD__ . PHP_EOL; }
}
trait T2 {
use T1;
}
trait T3 {
use T1;
}
class Test {
use T2, T3;
}
$t = new Test;
$t->f1();
This will output:
PHP Fatal error: Trait method f1 has not been applied, because there are collisions with other trait methods on Test in diamond.php on line 24
To make it work you shall use “insteadof”:
class Test {
use T2, T3 {
T2::f1 insteadof T3;
}
}
Now you get this expected output:
T1::f1
That’s fine so far. Anyway, it burdens the programmer with the decision which path through the inheritance hierarchy to use, a hierarchy that’s no longer a tree but a graph with cycles. Hopefully, he’s not doomed with a poor documented library. In a non-trivial project this is not always the case. Here you may soon find yourself lost in a complex inheritance hierarchy which is even more complex if multiple inheritance is possible.
Though knowing it well from Scala I’m not a big fan of traits. They may make your code more expressive but they will make it harder to maintain. Interfaces seem to be less error-prone. In OO design, a deep inheritance hierarchy is usually considered bad design. A wide fan of traits should be as well. And the diamond is a gift from hell.
Powered by Tumblr; designed by Adam Lloyd and Ingo Schramm.