> This is a very well-written and well-thought through RFC, Dennis.  Nicely
> done.

Thank you!

> First of all, I have generally found the Bean-style getter/setter
approach to
> be a sign of poor encapsulation to begin with.  You shouldn't be mucking
with
> internal elements of an object in the first place, period.  More details on
> that here:
>
> http://www.garfieldtech.com/blog/property-visibility

Interesting post, although I can't say I agree with your views.  Your post
leaves me wondering how the user is expected to get or give data to a
class (for example, if I'm not supposed to do $customer->name or
$customer-getName(), how do I get the customers name?).  Additionally, you
are forgetting the real power of properties, which is the ability to
generate a get value, and process a set value, because get/set are
methods.  Properties are hardly just an indirection layer around an
underlying piece of data.


> However, I do see a potential use here if "properties" are treated
> conceptually as an entirely new concept and not as an indirection layer for
> class properties.  That would make them more akin to a class that has both
> methods and also implements ArrayAccess for "properties of the conceptual
> object, that may not have anything to do with internal class members."
>
> Viewed from that angle, I would have the following comments:
>
> - I strongly prefer the first syntax over the second.  The "property"
keyword
> improves readability, and the closing semi-colon is going to be
forgotten on a
> daily basis.  I still forget sometimes when to use it and when not to when
> writing Javascript. :-)  I cannot speak to the engine complexity
involved but
> from a PHP-autor point of view I believe the first syntax is much easier to
> use.

Right, the property keyword ties together with the "function" keyword, and
the semi-colon provides no real purpose to the author.  I have however
been told that the semi-colon is important from an internal perspective,
and would ease the implementation.


> - The use of identical syntax for class members and properties could create
> confusion as to which is which.  One could argue that is the point, but
only
> if we view properties as "just" an indirection layer around the physical
class
> members, which as I noted above I believe is a poor architectural design.
> There may not be an alternative here, but I mention it for completeness.

Using the same syntax is exactly the point of properties, and is what
gives them their power.  From the outside, properties should look and act
no differently than a simple variable class member.  This is encapsulation
at its greatest, because it hides the implementation!  It is not important
for a user of a class to know which is a property and which is a variable
underneath.  To use a different syntax would be to expose that.

Another cool side effect of variables and properties sharing the same
syntax, is that a variable can be replaced with a property that has the
same name, at any time (and vice-versa) and all code that calls that
member will continue to work.  This is eternally useful when writing class
libraries, where you want to do something more advanced with a class
variable internally, but do not want to break the API.


> - The layering of accessibility keywords I find intriguing, in a mostly
good
> way.  That can offer a great deal of flexibility to control who can do what
> when.  However, I am concerned about the confusion possible in the
> following:
>
> public property Hours {
>   get { return $this->seconds / 3600; }
>   protected set { $this->seconds = $value * 3600; }
> }
>
> The set method is then scoped with two different visibility directives:
public
> and protected.  Which applies?  Since both are optional (presumably) I
can see
> a potential here for confusion, especially if you also start mentioning
> keywords like final.  This should be made more definitive if possible.

The inner keywords always take precedence over the outer ones.  So in this
case by making the property "public", and the set "protected", it means
the "get" is public and the set is "protected".

This would mean the same thing:
property Hours {
    public get { return $this->seconds / 3600; }
    protected set { $this->seconds = $value * 3600; }
}

However, many people prefer to write it the way you quoted above, because
they don't like to leave the outer property without a visibility keyword. 
Perhaps a better choice (which is also equivalent) would have been this:
protected property Hours {
    public get { return $this->seconds / 3600; }
    set { $this->seconds = $value * 3600; }
}

Each one of these scenarios works as described in C#, and rarely causes
confusion.  The rule of thumb, is that if a get/set has no visibility
keyword, it inherits the one from the outer property.  I think that is
fairly simple.


> - If interfaces can declare properties (niiice), Traits should be able to
> provide them.  That provides full parallelism with methods, which I believe
> developers will expect.

I agree, properties should be able to be used with traits.


> - I am curious what the performance implication would be.  For instance,
I've
> benchmarked both magic property access (__get()) and ArrayAccess to be
around
> 4 times as slow as accessing a class member.
>
> http://www.garfieldtech.com/blog/benchmarking-magic
>
> Since in essence what is happening here is binding a function to fire
when a
> class member is accessed (given the identical syntax), I'm concerned that
> there would be a similar performance issue.  A 4x slower performance cost
> would make me avoid properties in favor of class members unless I
absolutely
> needed them.  A 2x or less I could see making more use of.

In C#, get and set methods of a property are compiled down to methods, and
calls to a property are changed to calls to those methods.  Therefore
their performance in C# is exactly that of a method call.  This is ideal,
since properties are meant to be a replacement for the standard
"getXYZ/setXYZ" design pattern.


> - Which also brings up an interesting question:
>
> class Foo {
>   public $a = 1;
>   protected $b = 2;
>
>   public property $a { get { return 3; } }
>   public property $b { get { return 4; } }
> }
>
> $f = new Foo();
> print $f->a . PHP_EOL; // Does this print 1 or 3?
> print $f->b . PHP_EOL; // Does this print 2 or 4, or error?

Both of those throw an error.  Properties and variables share the same
namespace, so you cannot define a property and variable with the same
name.

In C# we create private members with a lower case first letter, and public
members with an upper case first letter.  Because you will not want a
variable and a property named the same thing that are both public, this
usually works well to differentiate the two.  Since variable names are
case-insensitive in PHP, I would imagine PHP programmers would use the
underscore convention for private members.

This is what I would imagine seeing, and would compile:

class Foo {
   private $_a = 1;
   protected $_b = 2;

   public property $a { get { return 3; } }
   public property $b { get { return 4; } }
}

As you can see, there is no conflict or confusion this way.


> It gets even tricker when you introduce inheritance.  If a child class has
> a
> [property|class member] of the same name as a parent's [class member|
> property], then what?

This would be an overloading scenario.  You would overload a properties
getter/setter the same way you would overload a class method.  See the RFC
for details on inheritance.

> That's all I got for now.  Once again, nice RFP but still needs some
> thinking.

Of course, that is why I am harnessing your collective brains!

- Dennis


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to