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

Reply via email to