On 1/5/13 2:05 PM, Clint Priest wrote:
I like the alternate idea here, but I'm not sure what advantage it has over the 
current
situation?

See the "Pros" I listed. The primary being a clear differentiation between calling accessors and handling of the storage value associated with the property.

if an accessor is
already "in the call chain" then it will not be called again and "standard property 
rules"
take effect.

I see that as not simpler, and in fact leading to small bugs whenever getters/setters start becoming complex enough to call outside methods. Consider this:

class Foo {
  public $bar = 2 {
    get { return $this->calcBar(); }
  }
  public function calcBar() {
    return $this->bar * 3;
  }
}

echo $foo->bar; // 6

Within calcBar, "$this->bar" is the raw property (2), because hidden state has "unwrapped" (if you will) the property.

echo $foo->calcBar(); // 18

But here, within the first call of calcBar "$this->bar" triggers the getter. Now, of course, this is a foolish implementation, but within any method that could be called from the getter/setter, the symbol $this->bar could mean two completely different things; I think this is bad.

If, as I proposed, the storage var were only accessible as $prop in the accessor scopes, that would force authors to pass $prop to any supporting methods, clarifying intent. $this->bar would *always* be accessor calls.

In this model, I think infinite-loop-causing recursions would be easier to spot. If absolutely necessary we could always throw a fatal error whenever a getter was called twice in the same call chain.

Steve

AFAICT C# strictly separates fields ("properties" in PHP) and properties (a set 
of
accessors that emulate a field).

So the RFC provides 3 features (using C# terms):
1. A property API
2. A built-in storage variable so you don't need a separate field
3. Access to the storage variable as if it were a field of the same name

I think #2 is useful, avoiding the need to make a separate field just to make 
properties
read-only or type-hinted. However I think the complexity and confusion we're 
running
into is mostly caused by #3.

I think we might be better served by having another way to access this storage 
variable.

What if instead, we have the storage var available as $prop inside all the 
accessors?
These would be the default implementations:

  get         { return $prop; }
  set($value) { $prop = $value; }
  isset       { return $prop !== NULL; }
  unset       { $prop = NULL; }

Pros:
* Makes clear that $prop is regular var access, and that $this->PropertyName 
*always*
goes through accessors
* Gives isset/unset full access to the storage var, which allows doing things 
that can't
be done via setter/getter. E.g. you could actually implement a property being 
"unset",
which would be different from having it set to NULL.

Cons:
* Allows "evil", like having reads affect the storage var.
* Allows authors to hang themselves with recursive accessor calls, BUT those 
mistakes
would be apparent from looking at the code.

What functionality possible in the RFC would be lost by this?

Steve Clay



Steve Clay
--
http://www.mrclay.org/

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

Reply via email to