Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:35812 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 55011 invoked by uid 1010); 27 Feb 2008 08:08:57 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 54996 invoked from network); 27 Feb 2008 08:08:56 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 27 Feb 2008 08:08:56 -0000 Authentication-Results: pb1.pair.com header.from=php@stefan-marr.de; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=php@stefan-marr.de; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain stefan-marr.de from 82.96.83.42 cause and error) X-PHP-List-Original-Sender: php@stefan-marr.de X-Host-Fingerprint: 82.96.83.42 serv6.servweb.de Linux 2.4/2.6 Received: from [82.96.83.42] ([82.96.83.42:59969] helo=serv6.servweb.de) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 7B/CD-63317-69A15C74 for ; Wed, 27 Feb 2008 03:08:55 -0500 Received: from [192.168.0.25] (toolslave.net [85.88.12.247]) by serv6.servweb.de (Postfix) with ESMTP id 2E7EE5900A9; Wed, 27 Feb 2008 09:10:29 +0100 (CET) Message-ID: <47C51A9F.6020403@stefan-marr.de> Date: Wed, 27 Feb 2008 09:09:03 +0100 Reply-To: php@stefan-marr.de User-Agent: Thunderbird 2.0.0.9 (Windows/20071031) MIME-Version: 1.0 To: Joshua Thompson Cc: internals@lists.php.net, Marcus Boerger References: <47C317F4.2080301@stefan-marr.de> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit X-Redirected: By TestProxy Subject: Re: [PHP-DEV] Re: How to build a real Trait thing without exclusion and renaming From: php@stefan-marr.de (Stefan Marr) Hi Joshua, Joshua Thompson schrieb: > trait A { > public function smallTalk() { > return 'a'; > } > public function bigTalk() { > return strtoupper( $this->smallTalk() ); > } > } > trait B { > public function smallTalk() { > return 'b'; > } > public function bigTalk() { > return strtoupper( $this->smallTalk() ); > } > } > class Talker { > use A, B { > B::smallTalk instead A::smallTalk; > A::bigTalk instead B::bigTalk; > A::bigTalk as talk; > } > } > // now to the questions > $talker = new Talker(); > echo $talker->talk(); // What does this echo? My assumption is 'B'. > echo $talker->bigTalk(); // How about this? > echo $talker->smallTalk(); // This should be 'b'. Yes, right, the following class_at_runtime thing is would is produced from the class definition and represents the class at runtime: class_at_runtime Talker { public function smallTalk() { return 'b'; } public function bigTalk() { return strtoupper( $this->smallTalk() ); } public function talk() { return strtoupper( $this->smallTalk() ); } } > All the discussion seems to be on not breaking a traits methods and to > call internal methods from the trait. If this is the case, then the > answer to the second question would be 'A', which would not break the > trait's internal method call, but it seems less obvious to me. Yes, the trait is "broken" somehow. But IMHO that is the way traits should work (in its basic variant). The opportunity here is to name it not "break a trait" but interweave traits, instead. This will require a notion of white-boxed reuse, which might not be everybody's intend. If there is really the need for trait-local methods, I would really like the local keyword, since private as a keyword has already a valid semantics with traits. Private states, this method is merged into the trait (in case it does not conflict with another method from another trait and is excluded therefore) and takes part in common inheritance, but is not inherited to subclasses since it is private. The local-keyword would be needed here: //Example from the RFC with the cross-over conflict to be solved trait A { local function smallTalk() { echo 'a'; } public function bigTalk() { return strtoupper( $this->smallTalk() ); } } trait B { local function smallTalk() { echo 'b'; } public function bigTalk() { return strtoupper( $this->smallTalk() ); } } class Talker { use A, B { // the smallTalk methods do not need to be handled here, // since they are trait local and not visible to the class A::bigTalk instead B::bigTalk; B::bigTalk as talk; // in my original example the is A but B // makes more sense } } This would result in the following: class_at_runtime Talker { function \0A\0smallTalk() { return 'a'; } function \0B\0smallTalk() { return 'b'; } public function bigTalk() __Origin:A { return strtoupper( $this->smallTalk() ); // here we will have to // mess around with the method-lookup, to achieve a // complete "alpha-renaming" (even for call_user_f*) } public function talk() __Origin:B { return strtoupper( $this->smallTalk() ); //same as above } } This would result in: $t = new Talker(); echo $t->bigTalk(); // echos A echo $t->talk(); // echos B Maybe this is the way most users would be comfortable with, but it is a bit more complex and I think we would need here the "local"-keyword definitely. Kind Regards Stefan