Hi Larry,

>>> 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.
>
> The idea of a ->getName() method for retrieving a person's name is fine.
>   My point there is that any assumption that it corresponds to a ->name
> class member (as Bean definitions require) is invalid on its face.  (The
> context there is a lengthy ongoing debate regarding the use of public
> vs. protected class members, with my basic point being that class
> members are an implementation detail and if you care about them in the
> first place then you have a bug.  Yes, it's a deliberately stringent
> position.)

Right, I think I understand the whole "Bean" thing now.  Its just a
struct, but has get/set methods instead of public properties?  In that
case, that is rather silly.  A get/set method should not be required to
correspond to any underlying value.  A get could even return a constant,
inline value for that matter.  It shouldn't matter what a get returns, as
long as it returns something!

I do not agree with "class members are an implementation detail".  I would
say "private/protected members/methods are an implementation detail",
which is true no matter how you slice it.  There are perfectly valid
reasons for exposing public class members.  Heck I make classes that are
just a set of public class members, and do not even have methods.  This is
what a "struct" is in C, C++ and C#.  Its just a storage container (like a
bean in java, but without silly methods for every class member).  Arguably
an array could be used for this, but an array has less structure and is
not properly suited for a well-defined type.


> What I'm seeing here is that whether properties are intended as an
> indirection layer for class members (eg, a more robust __get/__set) or
> not is a fuzzy question.  On the one hand they are (since the goal of
> the syntax is to make it irrelevant to the caller which is happening),
> but on the other they're supposed to be something different that can do
> all kinds of on the fly behavior.

Properties can be thought of as a __get/__set that only handle a single
"class member name" each.  They are for single members, while __get/__set
is generically for all members.  I can see how you would call
"__get/__set" and indirection layer because, since you are handling the
values generically, doing anything other than indirection is too
complicated.  But when you are writing accessors for a single defined
member, its easier to be more robust - you can do anything you could do in
a normal method.


>>> - 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.
>
> Is this consistent with methods?  Do those share a namespace, too?  (I
> don't actually recall off the top of my head.)

methods and variables have their own namespaces.  This is because they are
called differently:

// variable $a
print $f->a;
// method a()
print $f->a();

But variables and properties would be called the same way (both $f->a;). 
Because of this, they need to share the same namespace in order to avoid
ambiguity.  This is in fact a feature of properties, because this way an
existing variable can later be replaced with a property, and all calling
code will continue to work (or at least will compile).


>> 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.
>
> True, although for the record I have always detested the underscore
> prefix on variables as a difficult to read hack. :-)

To be honest, I also detest the underscore prefix.  In C# we use camel
case for public and pascal case for private, but because PHP is
case-insensitive, that (very unfortunately) is not possible.

C# example:

class Foo {
    private int fooBar = 1;
    protected int fooBaz = 2;

    public int FooBar { get { return 3; } }
    public int FooBaz { get { return 4; } }
}

print(fooBar);// 1
print(FooBar);// 3


- Dennis


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

Reply via email to