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" <[EMAIL PROTECTED]>
<http://www.schmalls.com>

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to