Hi Chad,
> 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. > > ----------- Interesting, however I don't see anything tangible in your proposal that would give any benefit over just using regular methods. Besides, I think your proposal would serve a very different purpose than my property proposal. > 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? Interesting. So you are saying that once a word is a keyword in PHP, it cannot be used as a name, anywhere? So for example, you are saying I cannot create a variable called $function? If that is the case, that is extremely odd. I would expect that get/set could be keywords when used in the right location (inside a property definition, but outside of the property body), but anywhere else they should be able to be used as a regular name... Is there some way that could be possible? - Dennis -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php