Re: How to build a real Trait thing without exclusion and renaming

From: Date: Thu, 28 Feb 2008 02:54:28 +0000
Subject: Re: How to build a real Trait thing without exclusion and renaming
References: 1 2  Groups: php.internals 
Request: Send a blank email to internals+get-35837@lists.php.net to get a copy of this message
Andi Gutmans wrote:
Hi Stefan, I think the discussion is going in the right direction but personally I had to think really hard to figure out what this code was going to do :) The following is a suggestion which takes into account some of the discussions we've had including points both Lukas and Marcus have made on this list. I have not thought through all of the implementation details but I am quite sure we could implement such behavior. The following code shows a few things: - local properties which can be used in self-contained functionality. The storage is guaranteed to stay internal and will not clash with the aggregating class. - methods are by default hidden to the aggregating class and bound to the trait (as Marcus pointed out the method name would be mangled with the trait's name) - You can expose any method you want either by doing a "use TraitA *" for all methods or by explicitly exposing methods to a specific method in the class. Note: This is the equivalent of aliasing. The original mangled method in the Trait doesn't disappear but you can override it with a new method. Unlike what some have said that this is better solved with MI or Delegation as opposed to Traits I don't subscribe to that. I believe this suggestion still gives you the benefits of copy&paste ala Traits but adds more structure, a more useful ability to encapsulate functionality which is very often the case when Trait like functionality is needed (stateful traits), and most important, I think it's easy to understand and read. trait MyDebug { local $counter = 1; function showTrace() { printf("Called this %d time(s)\n", $this->counter++); debug_backtrace(); } } trait MyTicks { local $counter = 0; function logIncrement() { // Log when we incremented the counter } function incTicks() { $this->logIncrement(); return $this->counter++; } } class MyClock { use MyDebug *; use MyTicks { timeInTicks = inTicks; // Don't want to see logIncrement() } function display() {...} } Andi
I was working on a detailed RFC of something along these lines. I didn't include the local keyword, instead I went the route of stateful traits and forced the definition of which scope in the class. I also tried to keep the number of keywords to 1 (trait). I will keep working on it, and hopefully post it tomorrow for review. -- "Joshua Thompson" <spam.goes.in.here@gmail.com> <http://www.schmalls.com>

« previous php.internals (#35837) next »