Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:50834 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 8154 invoked from network); 2 Dec 2010 19:49:46 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 2 Dec 2010 19:49:46 -0000 Authentication-Results: pb1.pair.com smtp.mail=chadfulton@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=chadfulton@gmail.com; sender-id=pass; domainkeys=bad Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.214.170 as permitted sender) DomainKey-Status: bad X-DomainKeys: Ecelerity dk_validate implementing draft-delany-domainkeys-base-01 X-PHP-List-Original-Sender: chadfulton@gmail.com X-Host-Fingerprint: 209.85.214.170 mail-iw0-f170.google.com Received: from [209.85.214.170] ([209.85.214.170:58919] helo=mail-iw0-f170.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 78/95-07252-958F7FC4 for ; Thu, 02 Dec 2010 14:49:46 -0500 Received: by iwn36 with SMTP id 36so1943840iwn.29 for ; Thu, 02 Dec 2010 11:49:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:mime-version:received:in-reply-to :references:from:date:message-id:subject:to:content-type; bh=pTxx07l0S6WfIUHBS+nh9Q7kL0AZPPaXMzgm8AKp2yc=; b=Ex0k4mjRG5yU5wgGajxLYG13A7IkZqPtymdXDl+5Nk7bku5n8CbyINgQ9/gfhisvCt t5RXCkpxrzVi9DIr4PF5ScfMCLieV8BcNv9J3ehitFl/QhOm8YHw52KVcodpJPa6GS/K jk1hEHv1l/KrHz1BnNbUAvtnc2axkbiHz07Pk= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :content-type; b=Xi26IqOuYYjzibnnGjphcg68g6RpLOqLMGGl0QXJ2d5N7q1ZoYLC9klqEhzOGTRwjw UMXj6/WHSI0gCzngrNd2lFMvcXZtHBNQNiLxLnfPJ2xCNvB1VU7SRJ/bj0TqoGc5+WGQ z34gjCyhoC+eU2vdZ346/SHeTDY9V+Fup1ByE= Received: by 10.231.15.138 with SMTP id k10mr702765iba.17.1291319383030; Thu, 02 Dec 2010 11:49:43 -0800 (PST) MIME-Version: 1.0 Received: by 10.231.203.19 with HTTP; Thu, 2 Dec 2010 11:49:21 -0800 (PST) In-Reply-To: References: <003601cb8fd0$f6494e80$e2dbeb80$@com> <4CF3B855.5010406@sugarcrm.com> <003401cb8fee$1be39840$53aac8c0$@com> <2450924ae03481f5b1382a7f00e5743d.squirrel@webmail.basnetworks.net> <4CF50245.5020807@sugarcrm.com> <4CF5118B.2030300@sugarcrm.com> <1faa4c3db62771335db714507ac2adfa.squirrel@webmail.basnetworks.net> <4CF613EB.40200@sugarcrm.com> <8b46dd8e3e991cfe87550a9c55d9ecd8.squirrel@webmail.basnetworks.net> Date: Thu, 2 Dec 2010 11:49:21 -0800 Message-ID: To: "internals@lists.php.net" Content-Type: text/plain; charset=ISO-8859-1 Subject: Re: [PHP-DEV] RFC: C-sharp style property get/set syntax for PHP From: chadfulton@gmail.com (Chad Fulton) Having thought a bit about this, there are a couple of initial problems I see, and, more importantly, I'm not convinced that the stated problem (encapsulation) requires the addition of a new language construct (i.e. a "property" as distinct from a "class member"). In fact, I think it is better implemented in another way (see below). First of all from a confusion point of view, PHP already has defined "property" in a way that opposes your RFC's definition: property_exists() checks for the existence of what you call a "class member". So, at least, it seems to me you would have to find new terminology if you wanted to pursue this avenue of a new construct. In my opinion, however, there should not be a new construct, and "property" and "class member" should remain interchangeable descriptions of the same class construct. I think we can do this and still fix the encapsulation problem. (Note: this is a long e-mail, and probably best represented in a new RFC. I have also written this up more completely in the form of an RFC, but I don't want to clutter up the wiki's RFC page unless other people like this idea as well, so I'll add the RFC if it looks like it will be useful). For example, we could do: class Time { protected $time; // note that $seconds, $minutes, and $hours are, in this // implementation, "dummies", since they will never hold // a value, because their "set" functions only set the $time // class member. public $seconds; public $minutes; public $hours; public function issetTime($name) isset($hours,$minutes,$seconds) { return isset($this->time); } public function unsetTime($name) unset($hours,$minutes,$seconds) { unset($this->time); } public function setTime($name, $value) set($hours,$minutes,$seconds) { switch($name) { case 'hours': $this->time = $value * 3600; break; case 'minutes': $this->time = $value * 60; break; case 'seconds': $this->time = $value; break; } $this->seconds = $seconds; } public function getTime($name) get($hours,$minutes,$seconds) { switch($name) { case 'hours': return $this->time / 3600; break; case 'minutes': return $this->time / 60; break; case 'seconds': return $this->time; break; } } } with this syntax, you could group the properties like above or, if you preferred, you could have a different function for each property. for read only (similar for write only), including the possibility of asymmetry: class Time { protected $time; public $seconds; public $minutes; public $hours; // ... // now Time::$hours can only be set from inside the class / descendents protected function setHours($name, $value) set($hours) { $this->time = $value * 3600; } // but Time::$hours can still be retrieved from outside the class public function getHours($name) get($hours) { return $this->time / 3600; } } for interfaces: interface TimeClass { public function setHours($name, $value) set($hours); } This has a number of benefits: 1. This "acts like PHP", and also brings along features "out of the box" (a) The new syntax mimics the form of the syntax of closures ($x = function() use($a, $b) { // ... };), so it is somewhat familiar. (b) The arguments of the isset, unset, getters and setters is analogous to that in the __get and __set methods, so userland implementation will be familiar. (c) The getters and setters are still regular class methods, so they can be called as methods as usual (subject to visibility, of course) (d) Adds "shades" to the read-only and write-only concepts via visibility modifiers! (e) Isset / unset make sense now! E.g. that when unsetting $hours, we actually want to unset the time in general. In fact, this is preferred, because in the examples we've been looking at, the "magic" is in "grouping" the three class members (seconds, minutes, hours), and this implementation of isset and unset allow you to do just that grouping, without having to write 3 isset and 3 unset functions, as you would have to in the property definition. (f) This allows for much more compact class definitions, as you don't have to define getHours(), getMinutes(), getSeconds() individually if you don't want to (although it allows you the flexibility to do that if it's what you want). (g) Inheritance works out of the box. (h) Final keyword works out of the box. (i) Documentation works out of the box (just do it as you do it now, on the class members and the methods). (j) Interfaces work. (k) In the example above, the class could go ahead and set the Time::$time class member directly without incurring the overhead of the getter / setter functions! 2. Fixes the stated problems (a) Adds the syntactic sugar to complex getting and setting. (b) Gives read-only / write-only (c) Fixes the ambiguity of __get and __set in terms of what class members are defined. ----------- On another note, given our current parser, as I understand it, defining the new keywords of "get" and "set" will not be possible because of a BC break - for people using get and set as the names of classes, methods, or functions. This means that for both your RFC and for my suggestion, a new keyword will have to be found, unless this is put in a new major version and people are comfortable with it. I also think __get, __set are out because they are in use as the magic methods...any suggestions?