Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:51066 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 42776 invoked from network); 16 Dec 2010 22:32:08 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 16 Dec 2010 22:32:08 -0000 Authentication-Results: pb1.pair.com header.from=larry@garfieldtech.com; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=larry@garfieldtech.com; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain garfieldtech.com from 76.96.27.228 cause and error) X-PHP-List-Original-Sender: larry@garfieldtech.com X-Host-Fingerprint: 76.96.27.228 qmta15.emeryville.ca.mail.comcast.net Received: from [76.96.27.228] ([76.96.27.228:53897] helo=qmta15.emeryville.ca.mail.comcast.net) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id C0/82-29115-5639A0D4 for ; Thu, 16 Dec 2010 17:32:07 -0500 Received: from omta15.emeryville.ca.mail.comcast.net ([76.96.30.71]) by qmta15.emeryville.ca.mail.comcast.net with comcast id jxf61f00D1Y3wxoAFyXELo; Thu, 16 Dec 2010 22:31:14 +0000 Received: from earth.ufp ([98.220.236.211]) by omta15.emeryville.ca.mail.comcast.net with comcast id jyXD1f00G4aLjBW8byXDr7; Thu, 16 Dec 2010 22:31:14 +0000 Received: from localhost (localhost [127.0.0.1]) by earth.ufp (Postfix) with ESMTP id 1CEEDD7A65 for ; Thu, 16 Dec 2010 16:31:13 -0600 (CST) Received: from earth.ufp ([127.0.0.1]) by localhost (earth.ufp [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id b1Fk+uC4d8Ou for ; Thu, 16 Dec 2010 16:31:13 -0600 (CST) Received: from garfield.ad.palantir.net (unknown [209.41.114.202]) by earth.ufp (Postfix) with ESMTPSA id D56BFD79DA for ; Thu, 16 Dec 2010 16:31:12 -0600 (CST) Message-ID: <4D0A9330.1090109@garfieldtech.com> Date: Thu, 16 Dec 2010 16:31:12 -0600 User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.13) Gecko/20101207 Lightning/1.0b2 Thunderbird/3.1.7 MIME-Version: 1.0 To: internals@lists.php.net References: <89C52156-CF92-4DDB-8BA4-4ABF6883512C@stefan-marr.de> <581ACCE6-71A4-444F-A226-8D87E1B43EEF@stefan-marr.de> In-Reply-To: <581ACCE6-71A4-444F-A226-8D87E1B43EEF@stefan-marr.de> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] Traits and Properties From: larry@garfieldtech.com ("larry@garfieldtech.com") I am fine with this approach, with 2 caveats: - If you actually do want to make two traits use the same property, it looks like the answer here is "Either have no property and demand the existence of an accessor that returns by reference, or you can't write E_NOTICE-safe code". Is that true? - When the visibility collides, should we be folding to the most restrictive or least restrictive? I'm not sure myself; I'm more interested in your reasoning for going for most-restrictive. --Larry Garfield On 12/16/10 9:25 AM, Stefan Marr wrote: > Hi: > > From my point of view the right thing to do with regard to properties is defined in the test cases below. > > The rational behind providing this semantics is based on the fact that PHP allows to define properties dynamically anyway, so there is no way around properties. > However, there should be a way that a developer can notice that the code might not behave as expected in the composed class. > > It is true that behavior needs state to operate on, however, accessors are a common pattern and fully supported by traits. Furthermore, traits are not supposed to replace classes, and when a trait does more than just providing code that is to be easily reused, then the designed should ask the question whether that is not actually a class, which then provides the necessary guarantees to enforce the invariances the code expects. > > Thus, I would like to keep traits as a lightweight concept for code reuse. > > Best regards > Stefan > > --TEST-- > Conflicting properties should result in a notice. > Property use is discorage for traits that are supposed to enable maintainable > code reuse. Accessor methods are the language supported idiom for this. > --FILE-- > error_reporting(E_ALL); > > trait THello1 { > public $foo; > } > > trait THello2 { > private $foo; > } > > class TraitsTest { > use THello1; > use THello2; > } > > var_dump(property_exists('TraitsTest', 'foo')); > ?> > --EXPECTF-- > Notice: Trait THello1 and THello2 define the same property in the composition of TraitsTest. This might be incompatible, to improve maintainability consider using accessor methods instead. Class was composed in %s on line %d. > > bool(true) > > > > > --TEST-- > Non-conflicting properties should work just fine. > --FILE-- > error_reporting(E_ALL); > > trait THello1 { > public $hello = "hello"; > } > > trait THello2 { > private $world = "World!"; > } > > class TraitsTest { > use THello1; > use THello2; > function test() { > echo $this->hello . ' ' . $this->world; > } > } > > var_dump(property_exists('TraitsTest', 'hello')); > var_dump(property_exists('TraitsTest', 'world')); > > $t = new TraitsTest; > $t->test(); > ?> > --EXPECTF-- > bool(true) > bool(true) > > hello World! > > > --TEST-- > Conflicting properties with different visibility modifiers should be merged > to the most restrictive modifier. > --FILE-- > error_reporting(E_ALL); > > trait THello1 { > public $hello; > } > > trait THello2 { > private $hello; > } > > class TraitsTest { > use THello1; > use THello2; > } > > $t = new TraitsTest; > $t->hello = "foo"; > ?> > --EXPECTF-- > Fatal error: Cannot access private property TraitsTest::$foo in %s on line %d > > On 11 Dec 2010, at 17:47, Stefan Marr wrote: > >> Hi: >> >> Traits do not provide any special provisioning for handling properties, especially, there is no language solution for handling colliding property names. >> The current solution/idiom for handling state safely in a trait is to use either abstract set/get methods or an abstract get that returns a reference to the property in the class. >> >> However, at the moment it is possible to define properties in a trait: >> >> trait Foo { >> private $a; >> public $foo; >> } >> >> For the moment, that information is completely ignored, thus: >> >> class Bar { >> use Foo; >> } >> property_exists('Bar', 'a') === false >> >> >> Well, and that is a rather inconsistent status-quo. >> >> I would like to have that fixed in one or another way. >> >> One possibility would be to forbid property definition in a trait altogether. >> That reduces a bit the possibility to have wrong expectations about properties, however, the dynamic property creation is still possible. >> >> Another way would be to merge the properties in the composing class. >> The question here would be how to treat visibility modifiers: how to merge public and private, should it result in public, or private? >> And, to discorage users to go this way, should there be a STRICT notice? Options here are a notice whenever a property is defined in a trait, or whenever properties are silently merged. >> >> >> Comments very welcome. >> >> Thanks >> Stefan >> >> -- >> Stefan Marr >> Software Languages Lab >> Vrije Universiteit Brussel >> Pleinlaan 2 / B-1050 Brussels / Belgium >> http://soft.vub.ac.be/~smarr >> Phone: +32 2 629 2974 >> Fax: +32 2 629 3525 >> >> >> -- >> PHP Internals - PHP Runtime Development Mailing List >> To unsubscribe, visit: http://www.php.net/unsub.php >> >