Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:35837 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 9084 invoked by uid 1010); 28 Feb 2008 02:54:30 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 9068 invoked from network); 28 Feb 2008 02:54:30 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 28 Feb 2008 02:54:30 -0000 X-Host-Fingerprint: 72.198.16.221 ip72-198-16-221.ok.ok.cox.net Received: from [72.198.16.221] ([72.198.16.221:3362] helo=localhost.localdomain) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 36/91-14752-56226C74 for ; Wed, 27 Feb 2008 21:54:29 -0500 Message-ID: <36.91.14752.56226C74@pb1.pair.com> To: internals@lists.php.net Date: Wed, 27 Feb 2008 20:54:28 -0600 User-Agent: Thunderbird 2.0.0.12 (Windows/20080213) MIME-Version: 1.0 References: <47C317F4.2080301@stefan-marr.de> <698DE66518E7CA45812BD18E807866CE01506447@us-ex1.zend.net> In-Reply-To: <698DE66518E7CA45812BD18E807866CE01506447@us-ex1.zend.net> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Antivirus: avast! (VPS 080227-0, 02/27/2008), Outbound message X-Antivirus-Status: Clean X-Posted-By: 72.198.16.221 Subject: Re: [PHP-DEV] How to build a real Trait thing without exclusion and renaming From: spam.goes.in.here@gmail.com (Joshua Thompson) 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"