horizontal reuse: traits vs. grafts
| From: | Lukas Kahwe Smith | Date: | Wed, 24 Mar 2010 10:50:03 +0000 |
| Subject: | horizontal reuse: traits vs. grafts | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-47556@lists.php.net to get a copy of this message | ||
Ahoi,
Thought it would be better to open up a new thread and also using the term "horizontal
reuse" in the subject so that we make it clearer that there are actually two approaches. Here
is the URL for Stefan's proposal:
http://wiki.php.net/rfc/horizontalreuse
"In case of the above definition of Talker, PHP will show a waring that there have been
conflicts and name the methods smallTalk() and bigTalk() as the reason of this conflict. Therefore,
neither of the given implementations will be available in the class."
I think this is a fundamental decision, should it be a warning or a fatal error? Generally I prefer
PHP to keep on going whenever it can. I guess in most cases if we stick to a warning the user will
end up with a fatal error anyway, but it might not be so clear why the given method is unavailable.
But there should still be a warning, which I guess cannot be suppressed all that easily.
(@Stefan: didnt want to start editing minor typo's in the RFC .. s/waring/warning .. that typo
can be found in other places too)
"Since the new name is recognized as an additional method, the bigTalk method still has to be
excluded. Otherwise, PHP would print a warning that two methods from Traits have a conflict and are
excluded. The introduction of a new name is not renaming and references in methods to a given method
name aren't changed either. On the first look this may sound strange, but it provides the
opportunity to build Traits and even hierarchies of Traits which fit together very well."
The third sentence is not so clear to me, but if I guess it its also just a typo as it makes more
sense to me when replacing "renaming" to "result in renaming". But maybe you
could tweak that paragraph to be a bit clearer. For example its still not totally clear to me why
aliasing doesn't imply inclusion, I guess its definitely more flexible. How will things work
when traits have overlapping method names when other methods of the given traits call these
overlapping methods?
trait A {
public function smallTalk() {
$this->bigTalk();
}
public function bigTalk() {
echo 'A';
}
}
trait B {
public function smallTalk() {
$this->bigTalk();
}
public function bigTalk() {
echo 'B';
}
}
class Talker {
use A, B {
B::smallTalk instead A;
A::bigTalk instead B;
B::smallTalk as talk;
}
}
What is there anyway to ensure that when Talker::talk() is called that B::bigTalk() is still called
and not A::bigTalk() because I want to maintain the "integrity" of each trait? Is that
what you mean with its "not renaming and references in methods to a given method name
aren't changed either" as in it will indeed call B::bigTalk()? Reading further long I
however see that "This leads to missing features like recursion for methods introduced by
aliases." Also I guess exactly this is the key difference to Grafts.
Reading further about Grafts, I must say I really like that approach. I mean we have talked about
traits for quite a bit already, but I feel like I got how Grafts work the first time reading. I also
like the fact that since Grafts are just classes, people can integrate them as they see fit, like
they can use delegation if they are still on an older version of PHP or use Grafts. I also envision
that there will be less surprises when using Grafts and this fits well with the approach to keeping
the barrier to entry low for PHP development.
regards
Lukas Kahwe Smith
mls@pooteeweet.org