rfc:propertygetsetsyntax-as-implemented:change-requests
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
Previous revisionNext revision | |||
— | rfc:propertygetsetsyntax-as-implemented:change-requests [2013/01/02 21:13] – [Syntax Change] cpriest | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== v1.1 -> v1.2 ====== | ||
+ | * [[rfc/ | ||
+ | |||
+ | |||
+ | ===== Current Consensus Changes ===== | ||
+ | |||
+ | ==== Syntax Change ==== | ||
+ | < | ||
+ | |||
+ | Allow syntax to use parenthesized syntax as well. | ||
+ | |||
+ | <code php> | ||
+ | class TimePeriod { | ||
+ | private $Seconds; | ||
+ | |||
+ | public $Hours { | ||
+ | get() { return $this-> | ||
+ | set([TypeHint] $value) { $this-> | ||
+ | isset() { return isset($this-> | ||
+ | unset() { unset($this-> | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== read-only / write-only keywords ==== | ||
+ | < | ||
+ | |||
+ | read-only / write-only keywords will be eliminated, the issue will be pushed to userland developers who can enforce the same by coding something like this: | ||
+ | |||
+ | <code php> | ||
+ | class TimePeriod { | ||
+ | private $Seconds; | ||
+ | |||
+ | public $Hours { | ||
+ | get() { return $this-> | ||
+ | private final set($value) { throw new Exception(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | This was previously being debated, the full details of this are in the last section under " | ||
+ | |||
+ | ==== Automatically Implemented Accessors ==== | ||
+ | [[https:// | ||
+ | |||
+ | v1.1 properties shadow (or over-ride) accessors, so if an accessor exists and a property is defined (only possible from within the accessors setter), then the property would shadow the accessor. | ||
+ | |||
+ | Nikita suggested that this should be inverted, that accessors shadow properties. | ||
+ | |||
+ | <code php> | ||
+ | class TimePeriod { | ||
+ | private $Seconds; | ||
+ | |||
+ | public $Hours { | ||
+ | get(); | ||
+ | set([TypeHint] $value); | ||
+ | isset(); | ||
+ | unset(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /* Would automatically be implemented as */ | ||
+ | |||
+ | class TimePeriod { | ||
+ | private $Seconds; | ||
+ | |||
+ | public $Hours { | ||
+ | get() { return $this-> | ||
+ | set([TypeHint] $value) { $this-> | ||
+ | isset() { return $this-> | ||
+ | unset() { $this-> | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Shadowing ==== | ||
+ | [[https:// | ||
+ | |||
+ | Accessors will shadow properties such that if a property named $foo is declared and an accessor for $foo is declared, the accessor will be used instead, only the accessor will have direct access to the underlying property. | ||
+ | |||
+ | <code php> | ||
+ | class TimePeriod { | ||
+ | private $Seconds; | ||
+ | |||
+ | public $Seconds { | ||
+ | get() { return $this-> | ||
+ | set($x) { $this-> | ||
+ | } | ||
+ | } | ||
+ | |||
+ | $o = new TimePeriod(); | ||
+ | $o-> | ||
+ | echo $o-> | ||
+ | </ | ||
+ | |||
+ | ==== isset / unset / attempted writes when no setter / attempted reads when no getter ==== | ||
+ | [[https:// | ||
+ | |||
+ | Invalid calls to isset/unset will fail silently and return false in the case of isset(), no warning/ | ||
+ | |||
+ | <code php> | ||
+ | class TimePeriod { | ||
+ | private $Seconds; | ||
+ | |||
+ | protected $Seconds { | ||
+ | get() { return $this-> | ||
+ | set($x) { $this-> | ||
+ | } | ||
+ | } | ||
+ | |||
+ | $o = new TimePeriod(); | ||
+ | isset($o-> | ||
+ | unset($o-> | ||
+ | </ | ||
+ | |||
+ | ==== Extra shorthand declaration ==== | ||
+ | |||
+ | Not much further support and good arguments against it, dropped. | ||
+ | |||
+ | ==== Interfaces ==== | ||
+ | [[https:// | ||
+ | |||
+ | An implementing class may specify a property with an appropriate access level to satisfy an accessor declaration requirement of an interface. | ||
+ | <code php> | ||
+ | interface i { | ||
+ | public $Seconds { get; } | ||
+ | } | ||
+ | |||
+ | class TimePeriod implements i { | ||
+ | |||
+ | /* Satisfies interface implementation requirements of interface i */ | ||
+ | public $Seconds; | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | ===== Being Debated ===== | ||
+ | |||
+ | ==== internal accessor method visibility / callability ==== | ||
+ | |||
+ | Some people are in favor of the internal functions being generated by an accessor declaration should be invisible and non-callable directly. | ||
+ | |||
+ | - v1.1 currently has them callable but not visible via reflection. | ||
+ | - v1.1 also alters any error which would reference an internal accessor and changes the error message to make sense from the perspective of the userland php developer. | ||
+ | - Examples: | ||
+ | - Fatal error: Cannot override final property getter TimePeriod:: | ||
+ | - Fatal error: Cannot set read-only property TimePeriod:: | ||
+ | |||
+ | === Type 1 ( Userland Programmer ) === | ||
+ | |||
+ | As a userland programmer, someone who cares nothing for " | ||
+ | |||
+ | === Type 2 ( Internals Programmer ) === | ||
+ | |||
+ | As an internals programmer, you want nothing hidden from you. If an accessor implements special %%__getHours()%% methods to work its magic, then you want to see them, you want to call them directly if you so choose. | ||
+ | |||
+ | **Unfortunately 80 to 95% of all people who use PHP are of the first type.** | ||
+ | |||
+ | Revealing these internal matters to them would only leave them confused, possibly frustrated //and likely asking about it to the internals mailing list to answer (repeatedly)// | ||
+ | |||
+ | ===== Issues ===== | ||
+ | |||
+ | ==== Static Accessors ==== | ||
+ | Stas pointed out a number of critical mistakes with the current implementation of static accessors. | ||
+ | - Class defined after a static accessor reference was made | ||
+ | - Dynamic variable use of an accessor --> $class:: | ||
+ | |||
+ | The current implementation " | ||
+ | |||
+ | Stas suggested that he could either help me to implement this more appropriately (such as changing the engine to make calls into zend_object_handler.c) so that these calls can be resolved dynamically, | ||
+ | |||
+ | **Update 12/ | ||
+ | ===== TODO ===== | ||
+ | - < | ||
+ | - < | ||
+ | - < | ||
+ | - < | ||
+ | - < | ||
+ | - < | ||
+ | - < | ||
+ | - < | ||
+ | - < | ||
+ | - < | ||
+ | - < | ||
+ | - < | ||
+ | - < | ||
+ | - < | ||
+ | |||
+ | ===== Previously Debated ===== | ||
+ | |||
+ | ==== read-only / write-only keywords ==== | ||
+ | read-only / write-only keywords replacement. | ||
+ | |||
+ | **For Clarity**: read-only enforces upon the defining class and all sub-classes that no setter may be defined, a type of final that restricts the defining of a setter. | ||
+ | |||
+ | Possible alternatives: | ||
+ | |||
+ | This would prevent sub-classes from changing the setter, however this would produce an automatically implemented setter which would be callable from within the defining class. | ||
+ | <code php> | ||
+ | class TimePeriod { | ||
+ | private $Seconds; | ||
+ | |||
+ | public $Hours { | ||
+ | get() { return $this-> | ||
+ | private final set([TypeHint] $value); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | This could be an alternative that could be implemented internally exactly the same as a read-only or write-only: | ||
+ | <code php> | ||
+ | class TimePeriod { | ||
+ | private $Seconds; | ||
+ | |||
+ | public $Hours { | ||
+ | get() { return $this-> | ||
+ | final set NULL; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | I have also suggested that perhaps the read-only and write-only functionality (type of final) is not even needed or desired. | ||
+ | |||
+ | **Possible Consensus: | ||
+ | <code php> | ||
+ | class TimePeriod { | ||
+ | private $Seconds; | ||
+ | |||
+ | public $Hours { | ||
+ | get() { return $this-> | ||
+ | private final set($value) { throw new Exception(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Shadowing ==== | ||
+ | v1.1 has properties shadow accessors, the suggestion is that this be inverted. | ||
+ | |||
+ | Specifically this means that in v1.1, if an accessor is defined and no property is defined, then the accessor will be used. But when a property is assigned/ | ||
+ | |||
+ | v1.2 Proposes that this be inverted such that if there is an accessor defined for a given property name, the accessor will always be used. The accessor would be able to get/ | ||
+ | |||
+ | v1.2 proposal seems to make the most sense however it would incur a slight (possibly *very* slight) performance penalty. | ||
+ | |||
+ | ==== isset / unset / attempted writes when no setter / attempted reads when no getter ==== | ||
+ | Stas suggested that since there is presently no cases where these can fail that with accessors these should never " | ||
+ | |||
+ | Three possible ways to go (maybe others): | ||
+ | - If all cases can be tested for during compilation, | ||
+ | - Let the compilation occur and at runtime when a disallowed action is attempted, emit a warning and move on. | ||
+ | - As is currently, either at compilation or at runtime we issue a fatal error and stop execution (probably least preferable if at runtime) | ||
+ | |||
+ | ==== Extra shorthand declaration ==== | ||
+ | Allow extra short declaration of an accessor: | ||
+ | <code php> | ||
+ | class TimePeriod { | ||
+ | public DateTime $date; | ||
+ | } | ||
+ | |||
+ | /* Would be equivalent to this */ | ||
+ | |||
+ | class TimePeriod { | ||
+ | public $date { | ||
+ | get() { return $this-> | ||
+ | set(DateTime $value) { $this-> | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Interfaces ==== | ||
+ | v1.1 fully allows accessors to be defined in interfaces and requires that those accessors be defined in implementing classes. | ||
+ | |||
+ | === Arguments For === | ||
+ | - From the outside observer of an interface, a class which defines a property has satisfied the requirement, | ||
+ | |||
+ | === Arguments Against === | ||
+ | - Additional overhead on interface checking, would only be allowed for a non-asymmetrical accessor | ||
+ | - Would give userland developers the ability to write poor code as properties are non-observable (object would not know its property was changed) | ||
rfc/propertygetsetsyntax-as-implemented/change-requests.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1