Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:50753 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 75340 invoked from network); 1 Dec 2010 01:09:52 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 1 Dec 2010 01:09:52 -0000 Authentication-Results: pb1.pair.com smtp.mail=larry@garfieldtech.com; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=larry@garfieldtech.com; sender-id=unknown Received-SPF: error (pb1.pair.com: domain garfieldtech.com from 76.96.27.243 cause and error) X-PHP-List-Original-Sender: larry@garfieldtech.com X-Host-Fingerprint: 76.96.27.243 qmta13.emeryville.ca.mail.comcast.net Received: from [76.96.27.243] ([76.96.27.243:51473] helo=qmta13.emeryville.ca.mail.comcast.net) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id A7/C3-53511-E50A5FC4 for ; Tue, 30 Nov 2010 20:09:51 -0500 Received: from omta21.emeryville.ca.mail.comcast.net ([76.96.30.88]) by qmta13.emeryville.ca.mail.comcast.net with comcast id dd5A1f0081u4NiLADd9osa; Wed, 01 Dec 2010 01:09:48 +0000 Received: from earth.ufp ([98.220.236.211]) by omta21.emeryville.ca.mail.comcast.net with comcast id dd9n1f0024aLjBW8hd9ncK; Wed, 01 Dec 2010 01:09:48 +0000 Received: from localhost (localhost [127.0.0.1]) by earth.ufp (Postfix) with ESMTP id CF96ED7A51 for ; Tue, 30 Nov 2010 19:09:46 -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 SmFNahLfLvUI for ; Tue, 30 Nov 2010 19:09:46 -0600 (CST) Received: from garfield.local (unknown [209.41.114.202]) by earth.ufp (Postfix) with ESMTPSA id 8F5CED7A48 for ; Tue, 30 Nov 2010 19:09:46 -0600 (CST) Message-ID: <4CF5A059.1050009@garfieldtech.com> Date: Tue, 30 Nov 2010 19:09:45 -0600 User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.12) Gecko/20101027 Lightning/1.0b2 Thunderbird/3.1.6 MIME-Version: 1.0 To: internals@lists.php.net References: <003601cb8fd0$f6494e80$e2dbeb80$@com> <4CF3B855.5010406@sugarcrm.com> <003401cb8fee$1be39840$53aac8c0$@com> <2450924ae03481f5b1382a7f00e5743d.squirrel@webmail.basnetworks.net> <4CF50245.5020807@sugarcrm.com> <1291127695.6129.16.camel@guybrush> <89020a2f897b85939c929ec28892158d.squirrel@webmail.basnetworks.net> In-Reply-To: <89020a2f897b85939c929ec28892158d.squirrel@webmail.basnetworks.net> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] RFC: C-sharp style property get/set syntax for PHP From: larry@garfieldtech.com ("larry@garfieldtech.com") On 11/30/10 6:29 PM, president@basnetworks.net wrote: >>> That is true for PHP variables. isset is basically saying "does this >>> variable exist", and unset is saying to get rid of it. >>> >>> Because properties (as defined in my RFC) are not a variable, but rather >>> a >>> set of methods, I do not think there would be any way to "unset" them. >>> Like a method, once they are defined, you cannot get rid of them. >>> Therefore "overloading" isset and unset would not make any sense here. >> >> This is different from the PHP Language then. You can isset() and >> unset() "native" properties. And use __isset() and __unset() magic >> methods. >> >> A new feature should be consistent with the language definition. > > Its not a matter of consistency - Properties, as a cross-language concept > are not meant to work that way. You need to think of a property as a set > of two methods that just have a pretty syntax. Methods cannot be unset, > and nor should properties be allowed to. isset() should simply tell us > whether a property with the specified name is part of the class or not. > > isset() in the way you suggest would just be confusing. It would allow is > to say that a property does not exist, when in fact it does exist. This > is not logical. Consistency with other languages must also be balanced against consistency within PHP. Both are important. Class members and both existing class-member-ish mechanisms (__magic and ArrayAccess) have the concept of isset/unset. A third class-member-ish (syntactically speaking) mechanism will be expected to have the same set of primitives. To not have them will be a major language WTF, because to a normal user of an object they *look* like class members, not methods, they *taste* like class members, not methods, so they should *act* like class members, not methods. Basically, properties can only be considered a drop-in replacement for class members (as you've stated, correctly, is one of the potential big wins for them) if they fully emulate their behavior. If they do not, then it is incorrect to say that they can be swapped in for a class member without changing an API. > __isset() is a whole different matter, without it we would have to assume > that every possible member name either exists or does not exist. This is > because __isset can handle ANY member name. > > Properties are bound to a single member name, therefore, they always > exist, unless you were to physically remove that property from the class, > which, like methods, that is not possible. No, but it can be easily emulated. Actually, I can even think of a concrete use case. Suppose I have an object that acts as a facade for a remote object over SOAP, REST, or whatever. It is using properties to represent attributes of a remote, say, insurance account. I want to know if a beneficiary has been set on the account. The most straightforward way to do so is if (isset($account->beneficiary)) { print $account->beneficiary->name; } If we are implementing such logic via __get(), we can do exactly that. If we are implementing it via properties, we should still be able to. Forcing the user to know that he needs to do it this way instead, but only if we're using properties rather than __get(): if ($account->hasBeneficiary()) { print $account->beneficiary->name; } is violating the principle of encapsulation as it means the user needs to know which of the three forms of $account->beneficiary happens to be in use. Thinking about properties further, actually, there's two other (related) considerations that always give me grief when dealing with __get: Reference returns and complex member variables. If I want a reference to a class member, I can very easily do this: $foo = &$bar->baz; If ->baz is accessed via __get(), then that only works if __get() is defined as function &__get($var) to start with. That's another encapsulation break. Similarly, the following does exactly what you'd expect with a normal class member: $foo->bar['baz']->narf = 'poink'; If $foo->bar is returned via __get(), though, then the above statement executes but does not actually save anything... *unless* __get() was defined to return by reference as above. Details of my adventures in __get() insanity here, including performance considerations: http://www.garfieldtech.com/blog/magical-php-call How would properties deal with those scenarios? (The answer may well be "it doesn't, screw off, that's way too esoteric", as it is for __get(), but we should at least consider if it's possible to handle those gracefully.) --Larry Garfield