On 11/30/10 6:29 PM, presid...@basnetworks.net wrote:
That is true for PHP variables.  isset is basically saying "does this
variable exist", and unset is saying to get rid of it.

Because properties (as defined in my RFC) are not a variable, but rather
a
set of methods, I do not think there would be any way to "unset" them.
Like a method, once they are defined, you cannot get rid of them.
Therefore "overloading" isset and unset would not make any sense here.

This is different from the PHP Language then. You can isset() and
unset() "native" properties. And use __isset() and __unset() magic
methods.

A new feature should be consistent with the language definition.

Its not a matter of consistency - Properties, as a cross-language concept
are not meant to work that way.  You need to think of a property as a set
of two methods that just have a pretty syntax.  Methods cannot be unset,
and nor should properties be allowed to.  isset() should simply tell us
whether a property with the specified name is part of the class or not.

isset() in the way you suggest would just be confusing.  It would allow is
to say that a property does not exist, when in fact it does exist.  This
is not logical.

Consistency with other languages must also be balanced against consistency within PHP. Both are important.

Class members and both existing class-member-ish mechanisms (__magic and ArrayAccess) have the concept of isset/unset. A third class-member-ish (syntactically speaking) mechanism will be expected to have the same set of primitives. To not have them will be a major language WTF, because to a normal user of an object they *look* like class members, not methods, they *taste* like class members, not methods, so they should *act* like class members, not methods.

Basically, properties can only be considered a drop-in replacement for class members (as you've stated, correctly, is one of the potential big wins for them) if they fully emulate their behavior. If they do not, then it is incorrect to say that they can be swapped in for a class member without changing an API.

__isset() is a whole different matter, without it we would have to assume
that every possible member name either exists or does not exist.  This is
because __isset can handle ANY member name.

Properties are bound to a single member name, therefore, they always
exist, unless you were to physically remove that property from the class,
which, like methods, that is not possible.

No, but it can be easily emulated.

Actually, I can even think of a concrete use case. Suppose I have an object that acts as a facade for a remote object over SOAP, REST, or whatever. It is using properties to represent attributes of a remote, say, insurance account. I want to know if a beneficiary has been set on the account. The most straightforward way to do so is

if (isset($account->beneficiary)) {
  print $account->beneficiary->name;
}

If we are implementing such logic via __get(), we can do exactly that.

If we are implementing it via properties, we should still be able to. Forcing the user to know that he needs to do it this way instead, but only if we're using properties rather than __get():

if ($account->hasBeneficiary()) {
  print $account->beneficiary->name;
}

is violating the principle of encapsulation as it means the user needs to know which of the three forms of $account->beneficiary happens to be in use.


Thinking about properties further, actually, there's two other (related) considerations that always give me grief when dealing with __get: Reference returns and complex member variables.

If I want a reference to a class member, I can very easily do this:

$foo = &$bar->baz;

If ->baz is accessed via __get(), then that only works if __get() is defined as function &__get($var) to start with. That's another encapsulation break.

Similarly, the following does exactly what you'd expect with a normal class member:

$foo->bar['baz']->narf = 'poink';

If $foo->bar is returned via __get(), though, then the above statement executes but does not actually save anything... *unless* __get() was defined to return by reference as above.

Details of my adventures in __get() insanity here, including performance considerations:

http://www.garfieldtech.com/blog/magical-php-call

How would properties deal with those scenarios? (The answer may well be "it doesn't, screw off, that's way too esoteric", as it is for __get(), but we should at least consider if it's possible to handle those gracefully.)

--Larry Garfield

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

Reply via email to