> -----Original Message-----
> From: Stefan Marr [mailto:[EMAIL PROTECTED]
> Sent: Monday, February 25, 2008 11:33 AM
> To: internals Mailing List; Marcus Boerger
> Subject: [PHP-DEV] How to build a real Trait thing without exclusion
> and renaming
>
>
> //here the new notion of combing traits and resolving conflicts
upfront
> class Talker {
>    use A, B {
>       B::smallTalk instead A::smallTalk;
>       A::bigTalk instead B::bigTalk;
>       A::bigTalk as talk;
>     }
>   }

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

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

Reply via email to