rfc:readonly_properties_v2

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:readonly_properties_v2 [2021/06/04 16:15] nikicrfc:readonly_properties_v2 [2021/07/20 15:37] (current) nikic
Line 2: Line 2:
   * Date: 2021-06-02   * Date: 2021-06-02
   * Author: Nikita Popov <nikic@php.net>   * Author: Nikita Popov <nikic@php.net>
-  * Status: Draft+  * Status: Implemented
   * Target Version: PHP 8.1   * Target Version: PHP 8.1
   * Implementation: https://github.com/php/php-src/pull/7089   * Implementation: https://github.com/php/php-src/pull/7089
Line 77: Line 77:
 class Test { class Test {
     public function __construct(     public function __construct(
-        public readonly int $prop = 0,+        public readonly int $= 0
 +        public readonly array $ary = [],
     ) {}     ) {}
 } }
  
 $test = new Test; $test = new Test;
-$test->prop += 1; +$test->+= 1; 
-$test->prop++; +$test->i++; 
-++$test->prop+++$test->i; 
-$ref =& $test->prop+$test->ary[] = 1; 
-$test->prop =& $ref; +$test->ary[0][] = 1
-byRef($test->prop);+$ref =& $test->i
 +$test->=& $ref; 
 +byRef($test->i);
 foreach ($test as &$prop); foreach ($test as &$prop);
 </PHP> </PHP>
Line 150: Line 153:
 </PHP> </PHP>
  
-As the property has no default value, the assignment in the constructor is initializing, and thus legal. The constructor property promotion feature was specifically design for forward-compatiblity with readonly properties.+As the property has no default value, the assignment in the constructor is initializing, and thus legal. The constructor property promotion feature was specifically designed for forward-compatibility with readonly properties.
  
-Readonly static properties are not supported. This is a technical limitation, in that it is not possible to implement readonly static properties non-intrusively. In conjuction with the questionable usefulness of readonly static properties, this is not considered worthwhile at this time.+Readonly static properties are not supported. This is a technical limitation, in that it is not possible to implement readonly static properties non-intrusively. In conjunction with the questionable usefulness of readonly static properties, this is not considered worthwhile at this time.
  
 ==== Inheritance ==== ==== Inheritance ====
Line 237: Line 240:
 </PHP> </PHP>
  
-However, it is possible to unset a readonly property prior to initialization, from the scope where the property has been declared. Just like with normal typed properties, explicitly unsetting the property makes it visibile to magic methods. In particular, this enables the usual lazy initialization pattern to work:+However, it is possible to unset a readonly property prior to initialization, from the scope where the property has been declared. Just like with normal typed properties, explicitly unsetting the property makes it visible to magic methods. In particular, this enables the usual lazy initialization pattern to work:
  
 <PHP> <PHP>
Line 261: Line 264:
  
 ''ReflectionProperty::setValue()'' can bypass the requirement that initialization occurs from the scope where the property has been declared. However, reflection cannot modify a readonly property that has already been initialized. ''ReflectionProperty::setValue()'' can bypass the requirement that initialization occurs from the scope where the property has been declared. However, reflection cannot modify a readonly property that has already been initialized.
 +
 +Similarly, closure rebinding can be used to bypass the initialization scope requirement.
 +
 +==== Serialization ====
 +
 +Readonly properties have no impact on serialization. As ''%%__unserialize()%%'' (and the legacy ''Serializable::unserialize()'') method are invoked without a prior constructor call, readonly properties will be in an uninitialized state and can be set by the ''%%__unserialize()%%'' implementation.
 +
 +This also applies to userland serializers and hydrators. As long as the object is created using ''ReflectionClass::newInstanceWithoutConstructor()'' or some other constructor-bypass, it is always safe to initialize readonly properties.
  
 ===== Rationale ===== ===== Rationale =====
Line 315: Line 326:
 This also ensures that a potential future "clone with" implementation will only be able to modify readonly properties from private scope and thus cannot bypass additional invariants imposed by the implementation when used from a different scope. This also ensures that a potential future "clone with" implementation will only be able to modify readonly properties from private scope and thus cannot bypass additional invariants imposed by the implementation when used from a different scope.
  
-This RFC overlaps with the [[rfc:property_accessors|Property Accessors RFC]]. In particular, it implements the "only implicit get" aspect, though not with the exact same semantics. As mentioned in the RFC, I'm not convinced that the full complexity of accessors is truly warranted. Supporting readonly properties and asymmetric visibility would cover a signficant portion of the use-cases, at a lower language complexity cost.+This RFC overlaps with the [[rfc:property_accessors|Property Accessors RFC]]. In particular, it implements the "only implicit get" aspect, though not with the exact same semantics. As mentioned in the RFC, I'm not convinced that the full complexity of accessors is truly warranted. Supporting readonly properties and asymmetric visibility would cover a significant portion of the use-cases, at a lower language complexity cost.
  
 It is worth noting that having a readonly property feature does not preclude introduction of accessors. C# supports both readonly properties and accessors. C# also provides properties with implicit backing storage through accessor syntax, but this is not the only way to do it. For example, Swift has special syntax for asymmetric visibility, rather than specifying visibility on implicitly implemented accessors. It is worth noting that having a readonly property feature does not preclude introduction of accessors. C# supports both readonly properties and accessors. C# also provides properties with implicit backing storage through accessor syntax, but this is not the only way to do it. For example, Swift has special syntax for asymmetric visibility, rather than specifying visibility on implicitly implemented accessors.
Line 331: Line 342:
 ===== Vote ===== ===== Vote =====
  
-Yes/No.+Voting started on 2021-07-01 and closes on 2021-07-15. 
 + 
 +<doodle title="Add readonly properties as proposed?" auth="nikic" voteType="single" closed="true"> 
 +   Yes 
 +   No 
 +</doodle>
  
rfc/readonly_properties_v2.1622823303.txt.gz · Last modified: 2021/06/04 16:15 by nikic