On Tue, May 4, 2021, at 5:33 AM, Nikita Popov wrote:
> Hi internals,
> 
> I'd like to present an RFC for property accessors:
> https://wiki.php.net/rfc/property_accessors
> 
> Property accessors are like __get() and __set(), but for a single property.
> They also support read-only properties and properties with asymmetric
> visibility (public read, private write) as a side-effect.
> 
> The proposal is modeled after C#-style accessors (also used by Swift), and
> syntactically similar to the previous
> https://wiki.php.net/rfc/propertygetsetsyntax-v1.2 proposal.
> 
> While I put a lot of effort into both the proposal and the implementation,
> I've grown increasingly uncertain that this is the right direction for us
> to take. The proposal turned out to be significantly more complex than I
> originally anticipated (despite reducing the scope to only "get" and "set"
> accessors), and I'm sure there are some interactions I still haven't
> accounted for. I'm not convinced the value justifies the complexity.
> 
> So, while I'm putting this up for discussion, it may be that I will not
> pursue landing it. I think a lot of the practical value of this accessors
> proposal would be captured by support for read-only (and/or private-write)
> properties. This has been discussed (and declined) in the past, but
> probably should be revisited.
> 
> Regards,
> Nikita

This is an amazingly detailed RFC, and I love most of it.  Thank you, Nikita!

Regarding complexity, can you elaborate on what the most 
complex/tricky/problematic parts are?  I'm mainly wondering if there are any 
parts that could be changed/slightly scaled back that would reduce the 
complexity more than it reduces capability.  (Eg, removing guard and lazy for 
now is a good call, IMO, since both can be emulated with the other two.)  All 
else equal, though, I would favor including all of it.

I would say that the visibility controls get us 70% of the benefit, not 80/90%, 
but I do agree that those are hugely beneficial in and of themselves.  *IF* you 
decide to scale it back, I would strongly recommend simply dropping the 
explicit accessors support and leaving the rest of the syntax the same.  That 
way we know it's forward-compatible should we decide in the future to 
re-introduce explicit accessors.

Some other questions:

1. Do setters have arbitrary access to the object?  Can they read/set arbitrary 
other values?  I'm thinking of something like this:

class Person {
  private string $firstName;
  private string $lastName;
  private string $nickname;
  private int $age;

  public string $fullName {
    get { return "$this->firstName $this->lastName"; }

    set($fullName) {
      if ($this->age > 50) throw new Exception('You are too old to change your 
name.');
      [$this->firstName, $this->lastName] = explode(' ', $fullName);
      $this->nickname = substr(0, 5, $this->firstName);
    }
  }  
}

(A contrived example, obviously.)

2. My knee-jerk thought is to agree with Marco and avoid references entirely, 
for the sake of everyone's sanity.  However, it is implied that &get is the 
only way to properly handle array property accessors.  Am I understanding that 
correctly?  If not, can you expand on array handling?  I'd happily jettison 
references if arrays can still be supported nicely without them.

3. The partial incompatibility with constructor promotion is understandable, 
but disappointing.  Is it at all possible to modify the promotion logic such 
that if a property is already defined with accessors, you can still promote it 
without a syntax error?  I am thinking of this case:

class Test {
  private int _$foo;
  public int $foo {
    get { return $this->_foo; }
    set ($foo) {
      if ($foo < 0) throw new InvalidArgumentException('Must be positive.');
      $this->_foo = $foo;
    }
  }

  public function __construct(public int $foo) {}
}

(Though a guard would be nicer, as it avoids the second variable, but there are 
other considerations there.)

4. I still don't love $value being a magic name in setters.  Being able to 
specify it explicitly is nice, and I would probably always use that myself (and 
push for it in coding standards), but would it be feasible to default it 
instead to the name of the variable?  Since that variable name cannot be a 
backing variable, we know that it won't conflict with anything, but it would be 
more self-documenting.


Thanks again, and I do hope you can be convinced all this effort is worth 
bringing to a vote. :-)

--Larry Garfield

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

Reply via email to