Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:35800 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 3970 invoked by uid 1010); 25 Feb 2008 19:33:04 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 3955 invoked from network); 25 Feb 2008 19:33:04 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 25 Feb 2008 19:33:04 -0000 Authentication-Results: pb1.pair.com smtp.mail=php@stefan-marr.de; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=php@stefan-marr.de; 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:41945] helo=serv6.servweb.de) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id E8/F8-11428-EE713C74 for ; Mon, 25 Feb 2008 14:33:03 -0500 Received: from [192.168.0.25] (toolslave.net [85.88.12.247]) by serv6.servweb.de (Postfix) with ESMTP id 2B3BA5900AC; Mon, 25 Feb 2008 20:34:34 +0100 (CET) Message-ID: <47C317F4.2080301@stefan-marr.de> Date: Mon, 25 Feb 2008 20:33:08 +0100 Reply-To: php@stefan-marr.de User-Agent: Thunderbird 2.0.0.9 (Windows/20071031) MIME-Version: 1.0 To: internals Mailing List , Marcus Boerger Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit X-Redirected: By TestProxy Subject: How to build a real Trait thing without exclusion and renaming From: php@stefan-marr.de (Stefan Marr) Hi, there is a lot of discussion going on about how traits should actually work in PHP. Currently, one of the main challenges seams to be to agree on a suitable mechanism to avoid breaking traits and there behavior. Eventually, there seams to be a large discomfiture on the excluding of methods and the interweaving of methods from different traits. I can agree on the opinion, that a unconditional exclude mechanism could accidentally break traits. But, I really do like the notion to be able to interweave traits and compose something new from it, which results in an overlapping construct using the appropriate methods for a concrete problem. Well, this implies traits are not units of black-boxed reuse. They do act really fine-grained and will require the knowledge about the used methods. Therefore, remove/exclude is bad, we need to get rid of it. There are some thoughts about aliasing. It seams to be not the natural/closest solution. Renaming semantics would be more natural, but it implies an exclude of the old method, too. Thus, renaming could accidentally breaking a trait. Eventually, renaming needs to be avoided, too. Ok, lets get a step back and recall what traits have to achieve. Traits try to be a construct to allow the reuse of a group of semantical related methods. They do not try to replace inheritance or the delegation patter. They are still valid means to reuse "complex behavior and state" things. Instead, the way to go with traits should be to reuse a small, predominantly independent (but semantically related) number of methods not justifying to build a full fledged class from them. Use traits to build a class from them, which adds some additional semantics/behavior to the set of methods got from the traits and build a complete blue print for objects from it. The main thing here seams to be that the current proposal does not fulfill the claim to combine the traits properly in the case of conflicts. Instead, there is a lot of potential to break the traits behavior. Let's try to find a notation where the traits are combined and conflicts are solved upfront, before being applied to the class. (This is even the way the implementation works right now.) To get rid of exclude and rename I would like to propose the following: //Example from the RFC with the cross-over conflict to be solved trait A { public function smallTalk() { echo 'a'; } public function bigTalk() { echo 'A'; } } trait B { public function smallTalk() { echo 'b'; } public function bigTalk() { echo 'B'; } } //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; } } The new ``use`` is defined as use with a list of traits to be included into the class. Since the exclude is not appropriated, conflicts could be solved a lot more explicitly with the new ``instead`` keyword. It has be read as: use B::smallTalk instead of A::smallTalk, which solves the conflict explicitly and avoids the need for an exclude operator with the power to exclude arbitrary methods. If more traits are combined it could look like ``A:foo instead B::foo, C::foo;`` To be able to reuse a method which is excluded this way the ``as`` keyword can be used. Read it like this: use A::bigTalk as talk in the class. Think with this, it is not possible to remove a method somehow. This could be even superior to the "hidding" thing and the notion of "trait-local" methods since everything/any part of the semantics is explicitly available in the notation. This has not been the case for other notations so far. The trait-local things are nice, but complex and I would prefer to avoid them, since the proposed traits have a very clean and simple semantics. May be we could introduce them as addition in a later release. Kind Regards Stefan