rfc:readonly_and_immutable_properties
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
rfc:readonly_and_immutable_properties [2020/06/20 18:59] – formating andrerom | rfc:readonly_and_immutable_properties [2020/06/21 18:47] (current) – formating andrerom | ||
---|---|---|---|
Line 11: | Line 11: | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | With the introduction of typed properties in PHP 7.4, properties have become far more powerful. However it is currently not possible to specify disconnected write vs read visibility for properties without having to resort to magic methods (getters and setters). This requires unnecessary boilerplate, | ||
- | This RFC resolves this issue by proposing: | + | **This is a early draft, currently looking for feedback on direction on what would make most sense to propose, especially |
- | - Language change to make it possibility | + | |
- | - Readonly attribute for properties and classes (all properties), if #1 is accepted this is merely syntax sugar | + | |
- | - Immutable attribute | + | |
+ | With the introduction of typed properties in PHP 7.4, properties have become far more powerful. However it is currently not possible to specify disconnected write vs read visibility for properties, such as readonly, without having to resort to magic methods (getters and setters). For immutable semantic it's even more cumbersome. This requires unnecessary boilerplate, | ||
- | //These three proposals will be offered as separate votes.// | + | This RFC resolves this issue by proposing a few options: |
+ | - Language approach: | ||
+ | - Change to make it possibility to specify write visibility disconnected from read. | ||
+ | - readonly keyword for write access, on property and class (implicit all properties) | ||
+ | - immutable keyword for write access, on property and class (implicit all properties) | ||
+ | - Attribute approach: | ||
+ | - Readonly attribute for properties, if #1.1/1.2 is accepted this is merely syntax sugar. | ||
+ | - Immutable attribute for properties, if #1.3 is accepted this is merely syntax sugar | ||
Line 72: | Line 76: | ||
<< | << | ||
+ | public string $name; | ||
+ | |||
+ | public function __construct(int $id, string $name) { | ||
+ | $this-> | ||
+ | $this-> | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | or just | ||
+ | |||
+ | <code php> | ||
+ | << | ||
+ | class User { | ||
+ | public int $id; | ||
public string $name; | public string $name; | ||
Line 88: | Line 108: | ||
==== Readonly ==== | ==== Readonly ==== | ||
- | This RFC differs from [[rfc: | + | This RFC aligns with [[rfc: |
Line 94: | Line 114: | ||
- | This RFC differs from[[rfc: | + | This RFC aligns with [[rfc: |
- | This RFC does __not__ align with the semantics of the recent [[rfc: | + | This RFC does __not__ align with the semantics of the recent [[rfc: |
Line 102: | Line 122: | ||
- | This RFC does not try to solve as wider use case as the different iterations of [[rfc: | + | This RFC does not try to solve as wide use case as the different iterations of [[rfc: |
- | + | ||
- | It's of this author' | + | |
- | Thus the author of this RFC believes what is proposed here should | + | However: |
+ | - Accessors overcomplicates readonly, and does not offer solutions to immutability | ||
+ | - There seems to be a higher need in the community | ||
+ | - Everything Accessors offers beyond disconnected read and write visibility for properties, can easily | ||
===== Proposal ===== | ===== Proposal ===== | ||
- | ==== 1. Language ability to set property visibility for write access | + | ==== Common semantics |
- | This proposal adds support for runtime-enforced write visibility for declared properties. The following example illustrates the basic syntax: | + | == References == |
+ | |||
+ | Attempting to pass a property value outside of allowed writable scope as a reference, results in an error. | ||
+ | |||
+ | |||
+ | ==== 1. Language Approach ==== | ||
+ | |||
+ | |||
+ | === 1.1 Language ability to set property visibility separately for write access === | ||
+ | |||
+ | This proposal adds support for enforced write visibility | ||
<code php> | <code php> | ||
Line 122: | Line 153: | ||
// Property is readonly in public scope | // Property is readonly in public scope | ||
public: | public: | ||
+ | | ||
+ | // Property is write-only in public and protected scope | ||
+ | private: | ||
public function __construct(int $id, string $name) { | public function __construct(int $id, string $name) { | ||
Line 130: | Line 164: | ||
</ | </ | ||
+ | The format is "< | ||
- | == References | + | == Reflection |
- | Attempting to pass a property value outside of allowed scope as reference, is an error. | + | When using reflection, methods such as '' |
+ | However with this proposal the following existing methods will represent read visibility for cases where it differs: | ||
+ | - '' | ||
+ | - '' | ||
+ | - '' | ||
- | //TODO: Cover how visibility is manipulated with reflection// | + | And for checking separate write visibility |
+ | - '' | ||
+ | - '' | ||
+ | - '' | ||
- | === 1.1. Language ability | + | '' |
- | This proposal adds support for runtime-enforced | + | //TODO: Expand this with modifier ints representing all variations and their names// |
+ | |||
+ | === 1.2 readonly keyword === | ||
+ | |||
+ | This proposal adds support for runtime-enforced | ||
<code php> | <code php> | ||
class User { | class User { | ||
- | // Property is immutable, can only be written to in __construct in private | + | // Property is readonly, and can only be written to in protected |
- | public:private | + | public |
+ | |||
+ | // Property is readonly, and can only be written to in private | ||
+ | protected readonly | ||
+ | // [assuming 1.1 is accepted] Invalid declaration (visibility is already stating property is readonly) | ||
+ | public: | ||
+ | |||
+ | public function __construct(int $id, string $name) { | ||
+ | $this-> | ||
+ | $this-> | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Keyword can also be set on class level, implicit setting it on all fields unless they have their own immutable attribute: | ||
+ | |||
+ | <code php> | ||
+ | readonly class User { | ||
+ | // Property is readonly, and can only be written to in protected scope | ||
+ | public int $id; | ||
+ | | ||
+ | // Property is readonly, and can only be written to in private scope | ||
+ | protected string $name; | ||
+ | |||
+ | // [assuming 1.1 is accepted] Invalid declaration (visibility is already stating property is readonly) | ||
+ | public: | ||
+ | |||
+ | public function __construct(int $id, string $name) { | ||
+ | $this-> | ||
+ | $this-> | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | == Readonly semantics == | ||
+ | |||
+ | An readonly property may only be written to in scope lower than what is define as its read+write visibility, so if visibility is public, it may only be written to in protected scope. | ||
+ | |||
+ | |||
+ | == Reflection == | ||
+ | |||
+ | When using reflection, methods such as '' | ||
+ | |||
+ | Furthermore the following method is proposed added to be able to detect readonly properties: | ||
+ | - '' | ||
+ | |||
+ | |||
+ | '' | ||
+ | |||
+ | //TODO: Expand this with specific modifier int for " | ||
+ | |||
+ | |||
+ | === 1.3 immutable keyword === | ||
+ | |||
+ | This proposal adds support for runtime-enforced immutable write visibility for declared properties. The following example illustrates the basic syntax: | ||
+ | |||
+ | <code php> | ||
+ | class User { | ||
// Property is immutable, can only be written to in __construct in protected scope | // Property is immutable, can only be written to in __construct in protected scope | ||
- | public immutable string $email; | + | public |
+ | |||
+ | // [assuming 1.1 is accepted] Property is immutable, can only be written to in __construct in private scope | ||
+ | public: | ||
public function __construct(int $id, string $email) { | public function __construct(int $id, string $email) { | ||
Line 159: | Line 266: | ||
</ | </ | ||
+ | Keyword can also be set on class level, implicit setting it on all fields unless they have their own readonly attribute: | ||
- | //TODO: There should perhaps | + | <code php> |
+ | immutable class User { | ||
+ | | ||
+ | public int $id; | ||
+ | |||
+ | // Property | ||
+ | protected string $email; | ||
+ | |||
+ | public function __construct(int $id, string $email) { | ||
+ | $this-> | ||
+ | $this-> | ||
+ | } | ||
+ | } | ||
+ | </code> | ||
== Immutable semantics == | == Immutable semantics == | ||
- | An immutable property may only be written to in __construct(), and unset in __destruct(). | + | An immutable property may only be written to in construct and in other methods involved in object creation |
- | Unless otherwise specified in visibility, the write/unset access is available | + | |
+ | Unless otherwise specified in visibility, the write/unset access is available within protected scope. | ||
- | ==== 2. Readonly | + | == Reflection == |
+ | |||
+ | When using reflection, methods such as '' | ||
+ | |||
+ | Furthermore the following method is proposed added to be able to detect immutable properties: | ||
+ | - '' | ||
+ | |||
+ | |||
+ | " | ||
+ | |||
+ | //TODO: Expand this with specific modifier int for " | ||
+ | |||
+ | ==== 2. Attributes ==== | ||
+ | |||
+ | With the recently accepted [[rfc: | ||
+ | |||
+ | However the Attribute RFC does not allow for what is being drafted here, so this would need suggesting a way for userland classes to tell parser / compiler to enhance language features. | ||
+ | |||
+ | **As such, maybe this should be completely omitted from the proposal?** Should we aim for concepts in 1.1, 1.2 and 3.0 in this RFC? | ||
+ | |||
+ | |||
+ | === 2.1 Readonly attribute | ||
Line 176: | Line 318: | ||
<code php> | <code php> | ||
- | use PHP\Attribute\Property\Readonly; | + | use PHP\Attribute\PropertyVisibility\Readonly; |
class User { | class User { | ||
<< | << | ||
- | public | + | public |
+ | // This property is not readonly | ||
public string $email; | public string $email; | ||
Line 191: | Line 334: | ||
</ | </ | ||
- | Attribute can also be set on class level, implicit setting it on all fields unless they have their own Property | + | Attribute can also be set on class level, implicit setting it on all fields unless they have their own PropertyVisibility |
<code php> | <code php> | ||
- | use PHP\Attribute\Property\Readonly; | + | use PHP\Attribute\PropertyVisibility\Readonly; |
<< | << | ||
class User { | class User { | ||
- | public | + | |
- | | + | public int $id; |
+ | | ||
+ | // This property is readable in protected scope and writeable in private | ||
+ | protected | ||
public function __construct(int $id, string $email) { | public function __construct(int $id, string $email) { | ||
Line 208: | Line 354: | ||
</ | </ | ||
+ | //For readonly semantics see proposal 1.2// | ||
- | //TODO: Define semantic in detail, see [[https:// | ||
+ | == Reflection == | ||
- | ==== 3. Immutable | + | //TODO: show example on reading / |
- | This proposal adds support for runtime-enforced immutable write visibility for declared properties. The following example illustrates the basic syntax: | + | |
+ | |||
+ | === 2.2. Immutable attribute === | ||
+ | |||
+ | This proposal adds a compiler attribute which implies a runtime-enforced immutable write visibility | ||
<code php> | <code php> | ||
- | use PHP\Attribute\Property\Immutable; | + | use PHP\Attribute\PropertyVisibility\Immutable; |
class User { | class User { | ||
<< | << | ||
- | public | + | public |
public string $email; | public string $email; | ||
Line 234: | Line 385: | ||
- | Attribute can also be set on class level, implicit setting it on all fields unless they have their own Property | + | Attribute can also be set on class level, implicit setting it on all fields unless they have their own PropertyVisibility |
<code php> | <code php> | ||
- | use PHP\Attribute\Property\Immutable; | + | use PHP\Attribute\PropertyVisibility\Immutable; |
<< | << | ||
class User { | class User { | ||
- | public | + | public |
public string $email; | public string $email; | ||
Line 252: | Line 403: | ||
- | //TODO: Define semantic in detail, | + | //For immutable semantics |
+ | |||
+ | == Reflection == | ||
+ | |||
+ | //TODO: show example on reading | ||
Line 259: | Line 415: | ||
Code that expects to be able to make properties writeable via reflection will have to adapt for new code taking advantage of this. | Code that expects to be able to make properties writeable via reflection will have to adapt for new code taking advantage of this. | ||
- | While ReflectionProperty:: | + | While '' |
Line 272: | Line 428: | ||
===== Performance ===== | ===== Performance ===== | ||
- | // | + | // |
===== Vote ===== | ===== Vote ===== | ||
As this is a language change, a 2/3 majority is required. | As this is a language change, a 2/3 majority is required. | ||
- | //RFC is in draft, and will undergo discussion phase before it is put for a vote.// | + | |
+ | ===== References ===== | ||
+ | |||
+ | |||
+ | * [[https://docs.microsoft.com/ | ||
+ | * [[https:// | ||
Line 290: | Line 451: | ||
Significant changes to the RFC are noted here. | Significant changes to the RFC are noted here. | ||
- | * 2020-06-20 Initial | + | * 2020-06-21 Initial |
rfc/readonly_and_immutable_properties.1592679577.txt.gz · Last modified: 2020/06/20 18:59 by andrerom