Final properties

php.internals

Michał Brzuchalski

10 years ago
Hey Internals, I'm new here. I've been wondering / working on adding final properties into PHP lang. This work started once I had the time to read the "Core Java for Impateient" by Cay S. Horstmann and found it very usefull to have final properties like Java. Those properties differ than `const` because they can be set at runtime - but only once in their lifetime. Such properties could be very usefull in Singletons, ValueObjects etc. impl like: class Money { public final $amount; public final $currency; public function __constructor($amount, $currency) { $this->amount = $amount; $this->currency = $currency; } } In above example there is even no need for getter because those properties are immutable through the final keyword, it means those properties cannot change their references just like in Java https://en.wikipedia.org/wiki/Final_(Java) I've already started some impl on own fork https://github.com/php/php-src/compare/master...brzuchal:final-properties I've got some basics in C programming, don't know yet if I can impl it complex. I was wondering if it is usefull in yours opinion or is it only my impression. I can provide an RFC if it sounds usefull and if I get Wiki karma Thanks
-- Michał Brzuchalski (aka brzuchal)

Marco Pivetta

10 years ago
Hi Michał, First of all: +1 to this: very useful for value objects! A few questions: * can you re-declare a final property in a sub-class, making it therefore non-final? (I have reasons to do that, related with altering states via mappers) * do we want to use `final`, or `immutable` for these properties? `final` seems to just be a confusing term here. * is this feature portable to variables in general? I realize that adding metadata to ZVals has huge performance implications, but it would be interesting to do that for performance improvements further down the line Cheers, Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/ On 4 April 2016 at 19:53, Michał Brzuchalski <michal@brzuchalski.com> wrote:

Michał Brzuchalski

10 years ago
Hi Marco, Ad. 1 it is posiible to redeclare in a sub-class final property as non-final, here is some gist presenting my current impl working like: https://gist.github.com/brzuchal/12ebda1efed59440a78ba43bff116728 Ad. 2. `final` means class variable (like static) or class instance property can not change their reference, it is impossible to replace zval in such property, in my opinion `immutable` is object behavior when using some methods you receive newly created (cloned) object which is changed exactly like `DateTimeImmutable` http://php.net/manual/en/datetimeimmutable.add.php Ad. 3 it would be awesome if there could be final variables in general, it would be quite stable if no one could change your variable, AFAIK zvals have IMMUTABLE flag which could be used, don't know it for sure I'm rather PHP dev than C there would be need some internals guru to ask if it's posiible. P.S. We've meet on PHPCon'15 in Poland, thanks for +1. Cheers,
-- Michał Brzuchalski (aka brzuchal) 2016-04-05 11:13 GMT+02:00 Marco Pivetta <ocramius@gmail.com>:

Marco Pivetta

10 years ago
Hi, On 5 April 2016 at 12:06, Michał Brzuchalski <michal@brzuchalski.com> wrote:
> Hi Marco, > > Ad. 1 it is posiible to redeclare in a sub-class final property as > non-final, here is some gist presenting my current impl working like: > https://gist.github.com/brzuchal/12ebda1efed59440a78ba43bff116728 >
Does this work for public properties as well?
> Ad. 2. `final` means class variable (like static) or class instance > property can not change their reference, it is impossible to replace zval > in such property, in my opinion `immutable` is object behavior when using > some methods you receive newly created (cloned) object which is changed > exactly like `DateTimeImmutable` > http://php.net/manual/en/datetimeimmutable.add.php >
I am aware of what `final` means in other languages, it just seems that everyone then needs to translate back and forth from `final` to `immutable`. In addition to that, `final` has different meaning in inheritance (re-used keyword), so this adds to the confusion for people unfamiliar with the feature.
> Ad. 3 it would be awesome if there could be final variables in general, it > would be quite stable if no one could change your variable, AFAIK zvals > have IMMUTABLE flag which could be used, don't know it for sure I'm rather > PHP dev than C there would be need some internals guru to ask if it's > posiible. > > P.S. We've meet on PHPCon'15 in Poland, thanks for +1. >
YW!
> > Cheers, > -- > Michał Brzuchalski (aka brzuchal) > > 2016-04-05 11:13 GMT+02:00 Marco Pivetta <ocramius@gmail.com>: > >> Hi Michał, >> >> First of all: +1 to this: very useful for value objects! >> >> A few questions: >> >> * can you re-declare a final property in a sub-class, making it >> therefore non-final? (I have reasons to do that, related with altering >> states via mappers) >> * do we want to use `final`, or `immutable` for these properties? >> `final` seems to just be a confusing term here. >> * is this feature portable to variables in general? I realize that >> adding metadata to ZVals has huge performance implications, but it would be >> interesting to do that for performance improvements further down the line >> >> Cheers, >> >> >> Marco Pivetta >> >> http://twitter.com/Ocramius >> >> http://ocramius.github.com/ >> >> On 4 April 2016 at 19:53, Michał Brzuchalski <michal@brzuchalski.com> >> wrote: >> >>> Hey Internals, >>> >>> I'm new here. I've been wondering / working on adding final properties >>> into >>> PHP lang. >>> >>> This work started once I had the time to read the "Core Java for >>> Impateient" by Cay S. Horstmann >>> and found it very usefull to have final properties like Java. >>> >>> Those properties differ than `const` because they can be set at runtime - >>> but only once in their lifetime. >>> Such properties could be very usefull in Singletons, ValueObjects etc. >>> impl >>> like: >>> >>> class Money { >>> public final $amount; >>> public final $currency; >>> public function __constructor($amount, $currency) { >>> $this->amount = $amount; >>> $this->currency = $currency; >>> } >>> } >>> >>> In above example there is even no need for getter because those >>> properties >>> are immutable through >>> the final keyword, it means those properties cannot change their >>> references >>> just like in Java >>> https://en.wikipedia.org/wiki/Final_(Java) >>> >>> I've already started some impl on own fork >>> https://github.com/php/php-src/compare/master...brzuchal:final-properties >>> I've got some basics in C programming, don't know yet if I can impl it >>> complex. >>> >>> I was wondering if it is usefull in yours opinion or is it only my >>> impression. >>> >>> I can provide an RFC if it sounds usefull and if I get Wiki karma >>> >>> Thanks >>> -- >>> Michał Brzuchalski (aka brzuchal) >>> >> >> >
As an additional question: how will this (eventually) play with typed properties? I am aware that you cannot declare a class named `final`, but that may change in future, so better factor it into any possible outcomes of the RFC. Cheers, Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/

Michał Brzuchalski

10 years ago
Hi, 2016-04-05 12:13 GMT+02:00 Marco Pivetta <ocramius@gmail.com>:
> Hi, > > On 5 April 2016 at 12:06, Michał Brzuchalski <michal@brzuchalski.com> > wrote: > >> Hi Marco, >> >> Ad. 1 it is posiible to redeclare in a sub-class final property as >> non-final, here is some gist presenting my current impl working like: >> https://gist.github.com/brzuchal/12ebda1efed59440a78ba43bff116728 >> > >
It works with public, private and protected properties.
> Does this work for public properties as well? > > >> Ad. 2. `final` means class variable (like static) or class instance >> property can not change their reference, it is impossible to replace zval >> in such property, in my opinion `immutable` is object behavior when using >> some methods you receive newly created (cloned) object which is changed >> exactly like `DateTimeImmutable` >> http://php.net/manual/en/datetimeimmutable.add.php >> > > I am aware of what `final` means in other languages, it just seems that > everyone then needs to translate back and forth from `final` to > `immutable`. In addition to that, `final` has different meaning in > inheritance (re-used keyword), so this adds to the confusion for people > unfamiliar with the feature. > > Wiki about Final in Java
https://www.wikiwand.com/en/Final_(Java)#/Final_variables says: # Final variables A final variable can only be initialized once, either via an initializer or an assignment statement. It does not need to be initialized at the point of declaration: this is called a "blank final" variable. A blank final instance variable of a class must be definitely assigned in every constructor of the class in which it is declared; similarly, a blank final static variable must be definitely assigned in a static initializer of the class in which it is declared; otherwise, a compile-time error occurs in both cases.[6] (Note: If the variable is a reference, this means that the variable cannot be re-bound to reference another object. But the object that it references is still mutable, if it was originally mutable.) I took the name from Java and only implemented behavior like that, thats wy I used `final`.
>> Ad. 3 it would be awesome if there could be final variables in general, >> it would be quite stable if no one could change your variable, AFAIK zvals >> have IMMUTABLE flag which could be used, don't know it for sure I'm rather >> PHP dev than C there would be need some internals guru to ask if it's >> posiible. >> >> P.S. We've meet on PHPCon'15 in Poland, thanks for +1. >> > > YW! > > >> >> Cheers, >> -- >> Michał Brzuchalski (aka brzuchal) >> >> 2016-04-05 11:13 GMT+02:00 Marco Pivetta <ocramius@gmail.com>: >> >>> Hi Michał, >>> >>> First of all: +1 to this: very useful for value objects! >>> >>> A few questions: >>> >>> * can you re-declare a final property in a sub-class, making it >>> therefore non-final? (I have reasons to do that, related with altering >>> states via mappers) >>> * do we want to use `final`, or `immutable` for these properties? >>> `final` seems to just be a confusing term here. >>> * is this feature portable to variables in general? I realize that >>> adding metadata to ZVals has huge performance implications, but it would be >>> interesting to do that for performance improvements further down the line >>> >>> Cheers, >>> >>> >>> Marco Pivetta >>> >>> http://twitter.com/Ocramius >>> >>> http://ocramius.github.com/ >>> >>> On 4 April 2016 at 19:53, Michał Brzuchalski <michal@brzuchalski.com> >>> wrote: >>> >>>> Hey Internals, >>>> >>>> I'm new here. I've been wondering / working on adding final properties >>>> into >>>> PHP lang. >>>> >>>> This work started once I had the time to read the "Core Java for >>>> Impateient" by Cay S. Horstmann >>>> and found it very usefull to have final properties like Java. >>>> >>>> Those properties differ than `const` because they can be set at runtime >>>> - >>>> but only once in their lifetime. >>>> Such properties could be very usefull in Singletons, ValueObjects etc. >>>> impl >>>> like: >>>> >>>> class Money { >>>> public final $amount; >>>> public final $currency; >>>> public function __constructor($amount, $currency) { >>>> $this->amount = $amount; >>>> $this->currency = $currency; >>>> } >>>> } >>>> >>>> In above example there is even no need for getter because those >>>> properties >>>> are immutable through >>>> the final keyword, it means those properties cannot change their >>>> references >>>> just like in Java >>>> https://en.wikipedia.org/wiki/Final_(Java) >>>> >>>> I've already started some impl on own fork >>>> >>>> https://github.com/php/php-src/compare/master...brzuchal:final-properties >>>> I've got some basics in C programming, don't know yet if I can impl it >>>> complex. >>>> >>>> I was wondering if it is usefull in yours opinion or is it only my >>>> impression. >>>> >>>> I can provide an RFC if it sounds usefull and if I get Wiki karma >>>> >>>> Thanks >>>> -- >>>> Michał Brzuchalski (aka brzuchal) >>>> >>> >>> >> > As an additional question: how will this (eventually) play with typed > properties? I am aware that you cannot declare a class named `final`, but > that may change in future, so better factor it into any possible outcomes > of the RFC. > > I don't know if it works with typed properties.
I can provide an RFC but need Wiki Karma (or smth like that) for my account (login: brzuchal) and don't know how to receive it.
> Cheers, > > Marco Pivetta > > http://twitter.com/Ocramius > > http://ocramius.github.com/ >
Cheers,
-- Michał Brzuchalski (aka brzuchal)

Chris Riley

10 years ago
On 5 April 2016 at 11:57, Michał Brzuchalski <michal@brzuchalski.com> wrote:
> Hi, > > 2016-04-05 12:13 GMT+02:00 Marco Pivetta <ocramius@gmail.com>: > > > Hi, > > > > On 5 April 2016 at 12:06, Michał Brzuchalski <michal@brzuchalski.com> > > wrote: > > > >> Hi Marco, > >> > >> Ad. 1 it is posiible to redeclare in a sub-class final property as > >> non-final, here is some gist presenting my current impl working like: > >> https://gist.github.com/brzuchal/12ebda1efed59440a78ba43bff116728 > >> > > > > > It works with public, private and protected properties. > > > > Does this work for public properties as well? > > > > > >> Ad. 2. `final` means class variable (like static) or class instance > >> property can not change their reference, it is impossible to replace > zval > >> in such property, in my opinion `immutable` is object behavior when > using > >> some methods you receive newly created (cloned) object which is changed > >> exactly like `DateTimeImmutable` > >> http://php.net/manual/en/datetimeimmutable.add.php > >> > > > > I am aware of what `final` means in other languages, it just seems that > > everyone then needs to translate back and forth from `final` to > > `immutable`. In addition to that, `final` has different meaning in > > inheritance (re-used keyword), so this adds to the confusion for people > > unfamiliar with the feature. > > > > Wiki about Final in Java > https://www.wikiwand.com/en/Final_(Java)#/Final_variables says: > > # Final variables > A final variable can only be initialized once, either via an initializer or > an assignment statement. It does not need to be initialized at the point of > declaration: this is called a "blank final" variable. A blank final > instance variable of a class must be definitely assigned in every > constructor of the class in which it is declared; similarly, a blank final > static variable must be definitely assigned in a static initializer of the > class in which it is declared; otherwise, a compile-time error occurs in > both cases.[6] (Note: If the variable is a reference, this means that the > variable cannot be re-bound to reference another object. But the object > that it references is still mutable, if it was originally mutable.) > > I took the name from Java and only implemented behavior like that, thats wy > I used `final`. > > > >> Ad. 3 it would be awesome if there could be final variables in general, > >> it would be quite stable if no one could change your variable, AFAIK > zvals > >> have IMMUTABLE flag which could be used, don't know it for sure I'm > rather > >> PHP dev than C there would be need some internals guru to ask if it's > >> posiible. > >> > >> P.S. We've meet on PHPCon'15 in Poland, thanks for +1. > >> > > > > YW! > > > > > >> > >> Cheers, > >> -- > >> Michał Brzuchalski (aka brzuchal) > >> > >> 2016-04-05 11:13 GMT+02:00 Marco Pivetta <ocramius@gmail.com>: > >> > >>> Hi Michał, > >>> > >>> First of all: +1 to this: very useful for value objects! > >>> > >>> A few questions: > >>> > >>> * can you re-declare a final property in a sub-class, making it > >>> therefore non-final? (I have reasons to do that, related with altering > >>> states via mappers) > >>> * do we want to use `final`, or `immutable` for these properties? > >>> `final` seems to just be a confusing term here. > >>> * is this feature portable to variables in general? I realize that > >>> adding metadata to ZVals has huge performance implications, but it > would be > >>> interesting to do that for performance improvements further down the > line > >>> > >>> Cheers, > >>> > >>> > >>> Marco Pivetta > >>> > >>> http://twitter.com/Ocramius > >>> > >>> http://ocramius.github.com/ > >>> > >>> On 4 April 2016 at 19:53, Michał Brzuchalski <michal@brzuchalski.com> > >>> wrote: > >>> > >>>> Hey Internals, > >>>> > >>>> I'm new here. I've been wondering / working on adding final properties > >>>> into > >>>> PHP lang. > >>>> > >>>> This work started once I had the time to read the "Core Java for > >>>> Impateient" by Cay S. Horstmann > >>>> and found it very usefull to have final properties like Java. > >>>> > >>>> Those properties differ than `const` because they can be set at > runtime > >>>> - > >>>> but only once in their lifetime. > >>>> Such properties could be very usefull in Singletons, ValueObjects etc. > >>>> impl > >>>> like: > >>>> > >>>> class Money { > >>>> public final $amount; > >>>> public final $currency; > >>>> public function __constructor($amount, $currency) { > >>>> $this->amount = $amount; > >>>> $this->currency = $currency; > >>>> } > >>>> } > >>>> > >>>> In above example there is even no need for getter because those > >>>> properties > >>>> are immutable through > >>>> the final keyword, it means those properties cannot change their > >>>> references > >>>> just like in Java > >>>> https://en.wikipedia.org/wiki/Final_(Java) > >>>> > >>>> I've already started some impl on own fork > >>>> > >>>> > https://github.com/php/php-src/compare/master...brzuchal:final-properties > >>>> I've got some basics in C programming, don't know yet if I can impl it > >>>> complex. > >>>> > >>>> I was wondering if it is usefull in yours opinion or is it only my > >>>> impression. > >>>> > >>>> I can provide an RFC if it sounds usefull and if I get Wiki karma > >>>> > >>>> Thanks > >>>> -- > >>>> Michał Brzuchalski (aka brzuchal) > >>>> > >>> > >>> > >> > > As an additional question: how will this (eventually) play with typed > > properties? I am aware that you cannot declare a class named `final`, but > > that may change in future, so better factor it into any possible outcomes > > of the RFC. > > > > I don't know if it works with typed properties. > I can provide an RFC but need Wiki Karma (or smth like that) for my account > (login: brzuchal) and don't know how to receive it. > > > > Cheers, > > > > Marco Pivetta > > > > http://twitter.com/Ocramius > > > > http://ocramius.github.com/ > > > > Cheers, > -- > Michał Brzuchalski (aka brzuchal) >
I started a discussion on this a while back, but it fizzled due to not having an elegant solution for the 'give me a new one of these with these values changed' problem. I would HIGHLY suggest not using the final keyword. If final is used as a keyword I would expect it to mean that this property definition cannot be changed in a child class. See: https://marc.info/?l=php-internals&m=144766539202647&w=2 Would be happy to pick this up again and help get the RFC created.

Marco Pivetta

10 years ago
On 5 April 2016 at 18:28, Chris Riley <t.carnage@gmail.com> wrote:
> > I started a discussion on this a while back, but it fizzled due to not > having an elegant solution for the 'give me a new one of these with these > values changed' problem. I would HIGHLY suggest not using the final > keyword. If final is used as a keyword I would expect it to mean that this > property definition cannot be changed in a child class. See: > https://marc.info/?l=php-internals&m=144766539202647&w=2 Would be happy > to pick this up again and help get the RFC created. >
Same concern here: just because Java decided that `final` means `assign-once`, it doesn't mean php should adopt it too. Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/

Fleshgrinder

10 years ago
/Sending this again because the mail server was down./ +1 from my side too for this proposal. Retrofitting immutability with additional keywords is not the nicest thing but PHP has no other way (same was true for Java when they added it). Using the *final* keyword while subclasses are able to override it is ambiguous in PHP because it already has the notion that something is not extensible (class) or overridable (method). Hence, I would either use a different keyword or implement two keywords (and two RFCs): 1. *immutable* for the functionality you are currently working on. 2. *sealed* for the above plus type not changeable. 3. *final* for the above plus not being overridable. Opening restrictions should be possible as with widening visibility in inheritance but making something more tight should not because it would violate the (implicit) interface of the parent class. In other words: OK == immutable -> mutable sealed -> immutable sealed -> mutable Fatal Error =========== immutable -> sealed immutable -> final sealed -> final final -> immutable final -> sealed final -> mutable mutable -> immutable mutable -> sealed mutable -> final Of course it would be nice to have the possibility to disable these restrictions while creating fakes, mocks, ... in unit tests. Sadly that is a feature that we don't have at all in PHP; e.g.: final class ClassUnderTest {} mock class TestDouble extends ClassUnderTest {} I do not think that there should be anything that prevents this new feature to work nicely together with typed properties. Of course I could be wrong here but then again it might only require a few adoptions of that feature to work nicely. One thing is for sure, *immutable*, *sealed* and *final* would also disallow references (e.g. sorting of an array); which is a good thing.
-- Richard "Fleshgrinder" Fussenegger

Larry Garfield

10 years ago
On 04/05/2016 05:13 AM, Marco Pivetta wrote:
>> Ad. 2. `final` means class variable (like static) or class instance >> property can not change their reference, it is impossible to replace zval >> in such property, in my opinion `immutable` is object behavior when using >> some methods you receive newly created (cloned) object which is changed >> exactly like `DateTimeImmutable` >> http://php.net/manual/en/datetimeimmutable.add.php >> > I am aware of what `final` means in other languages, it just seems that > everyone then needs to translate back and forth from `final` to > `immutable`. In addition to that, `final` has different meaning in > inheritance (re-used keyword), so this adds to the confusion for people > unfamiliar with the feature.
There's an important point here that should not be missed. If these values are "write once then locked', which I can definitely see as useful, we need to have another shot at modifying them from __clone(). If not, they are effectively useless for implementing objects in the style of DateTimeImmutable or the PSR-7 Request/Response objects. Locking after __construct or __clone (as appropriate) is done is fine, but if we can't clone-and-modify then I would pretty much never find value in this feature (no pun intended). I agree that final seems like a potentially confusing keyword, as every other use of final (AFAIK) means "subclass cannot change this", but that's not at all the meaning here. Another question, which unfortunately runs straight into the previous Properties RFC: If a public property is write-once, with the intent being that it's set from the constructor and then cannot be overridden but is publicly exposed... shouldn't an interface be able to declare it as well? It makes public properties safe to use in some cases, but you can't rely on that safely without an interface. (Which leads to "can interfaces define properties", which leads right back to "well what can you do with them", which leads back to the Properties RFC. Which I still want to see happen at some point if at all possible, as it would also subsume this question quite nicely.) --Larry Garfield

André Rømcke

10 years ago
> On Apr 11, 2016, at 06:59 , Larry Garfield <larry@garfieldtech.com> wrote: > ... > (Which leads to "can interfaces define properties", which leads right back to "well what can you do with them", which leads back to the Properties RFC. Which I still want to see happen at some point if at all possible, as it would also subsume this question quite nicely.) >
And by Properties RFC you mean Property Accessors Syntax RFC right? https://wiki.php.net/rfc/propertygetsetsyntax-v1.2

Larry Garfield

10 years ago
On 4/11/16 5:51 AM, André Rømcke wrote:
>> On Apr 11, 2016, at 06:59 , Larry Garfield <larry@garfieldtech.com> wrote: >> ... >> (Which leads to "can interfaces define properties", which leads right back to "well what can you do with them", which leads back to the Properties RFC. Which I still want to see happen at some point if at all possible, as it would also subsume this question quite nicely.) >> > And by Properties RFC you mean Property Accessors Syntax RFC right? > https://wiki.php.net/rfc/propertygetsetsyntax-v1.2
Yes, that thing.
-- --Larry Garfield

Fleshgrinder

10 years ago
On 4/11/2016 6:59 AM, Larry Garfield wrote:
> There's an important point here that should not be missed. If these > values are "write once then locked', which I can definitely see as > useful, we need to have another shot at modifying them from __clone(). > If not, they are effectively useless for implementing objects in the > style of DateTimeImmutable or the PSR-7 Request/Response objects. > Locking after __construct or __clone (as appropriate) is done is fine, > but if we can't clone-and-modify then I would pretty much never find > value in this feature (no pun intended). >
*__clone* support is indeed extremely important, very good point.
> I agree that final seems like a potentially confusing keyword, as every > other use of final (AFAIK) means "subclass cannot change this", but > that's not at all the meaning here. >
See other messages of mine in this thread.
> Another question, which unfortunately runs straight into the previous > Properties RFC: If a public property is write-once, with the intent > being that it's set from the constructor and then cannot be overridden > but is publicly exposed... shouldn't an interface be able to declare it > as well? It makes public properties safe to use in some cases, but you > can't rely on that safely without an interface. > > (Which leads to "can interfaces define properties", which leads right > back to "well what can you do with them", which leads back to the > Properties RFC. Which I still want to see happen at some point if at all > possible, as it would also subsume this question quite nicely.) >
I do not see the relation to the RFC (not judging the actual RFC because I liked the idea but never got into the topic to be able to judge) but I understand the concern. In my opinion interfaces in PHP are at the state of Java 7 interfaces (or even a direct copy) and their functionality must be extended at some point. Same happened in Java 8. That being said, I agree that properties should be allowed in interfaces, however, they must be automatically made *final* and immutable (where I proposed the *val* keyword). interface Example { DateTimeImmutable $created; function example(); } Transforms to: interface Example { final public DateTimeImmutable val $created; public function example(); } Otherwise no consumer could rely on the interface to not change. Also note that it does not require the RFC you mentioned because no setter, unset, nor isset is necessary or possible if we handle it like this. Support for mutable public properties is a different story but allowing them would destroy the encapsulation and I am against it without anyone bringing some good arguments that convince me.
-- Richard "Fleshgrinder" Fussenegger

Fleshgrinder

10 years ago
On 4/11/2016 7:12 PM, Fleshgrinder wrote:
> Support for mutable public properties is a different story but allowing > them would destroy the encapsulation and I am against it without anyone > bringing some good arguments that convince me. >
This of course would be different with the RFC you mentioned because then they are not simply public mutable properties anymore but a real method will be called that allows hooks. I wrote the above under the assumption of: interface Example { final public DateTimeImmutable var $created; } Where you end up not being able to hook into assignments and I am against the introduction of such a feature. ;)
-- Richard "Fleshgrinder" Fussenegger

Sebastian Bergmann

10 years ago
Am 05.04.2016 um 11:13 schrieb Marco Pivetta:
> First of all: +1 to this: very useful for value objects!
My thought exactly.
> do we want to use `final`, or `immutable` for these properties?
I have the same sentiment you have, that "final" would be confusing and "immutable" would be better. But it's also confusing to have the same concept another language has under a different name. Hm. I think I tend towards "immutable".

André Rømcke

10 years ago
> On Apr 9, 2016, at 09:39 , Sebastian Bergmann <sebastian@php.net> wrote: > > Am 05.04.2016 um 11:13 schrieb Marco Pivetta: >> First of all: +1 to this: very useful for value objects! > > My thought exactly.
Big +1 on this feature for the exact same reasons.
> >> do we want to use `final`, or `immutable` for these properties? > > I have the same sentiment you have, that "final" would be confusing > and "immutable" would be better. But it's also confusing to have > the same concept another language has under a different name. Hm. > > I think I tend towards "immutable".
I tend to as well. However as noted on misc C# pages* about immutable, this can be slightly confusing also; If the variable is ArrayAccess you will still be able to call offsetSet on it. “readonly"** would be another option, even if some might assume class can always write to it. Since there is no perfect name, maybe let the name be open for vote as part of RFC? To avoid to much focus on the naming during discussions/specification? * http://stackoverflow.com/a/6849164 ** https://msdn.microsoft.com/en-us/library/acdd6hb7.aspx

Niklas Keller

10 years ago
Another possible choice would be "readonly".

Sebastian Bergmann

10 years ago
Am 09.04.2016 um 12:55 schrieb Niklas Keller:
> Another possible choice would be "readonly".
Rather "writeonce", no?

Niklas Keller

10 years ago
Readonly is already used in the documentation for some things in the DOM book. Writeonce sounds strange. Sebastian Bergmann <sebastian@php.net> schrieb am Sa., 9. Apr. 2016 15:52:

Quim Calpe

10 years ago
There is a concept in storage devices that fits: Write Once Read Many (WORM) https://en.wikipedia.org/wiki/Write_once_read_many final class Value { public worm $name; public function __construct(string $name) { $this->name = $name; } } I'm not aware of any programming language using this term so it's a bit awkward in that sense... On Sat, Apr 9, 2016 at 4:54 PM, Niklas Keller <me@kelunik.com> wrote:

Lin Yo-An

10 years ago
I would prefer putting the "final" keyword before the "public". final public $items; Since we should emphasis "final" rather than "public"

Fleshgrinder

10 years ago
/Sending this again because the PHP mail server was down./ I thought some more about it and I think that the best choices would be *val* (for /value/) and *var* (for /variable/) as in Scala. Why? The *var* keyword is not going to be deprecated and its meaning is currently kind of ambiguous. I tried to assign it a new meaning in the thread about /Access and Visibility Modifiers/ thread (http://marc.info/?l=php-internals&m=146005798902985&w=2) but as Rowan Collins pointed out, it would be kind of weird to continue using *var* for anything related to access/visibility because it simply means something else; it means /variable/. The introduction of a counterpart to it would allow it to finally have a meaningful functionality and it would not introduce any kind of BC for old code. class Foo { val $x; var $y; val $z; } class Bar extends Foo { var $x; $y; $z; } The parent defines its property as being a *val* (immutable) and the extending class lifts this constraint by redeclaring it as a *var* (mutable). Doing so ensures that the developer must know what she is doing and hence makes the language overall more secure. There is no BC for the /y/ property because the parent is already mutable and implicit public (or hopefully /assembly visible/ in the future, see other references thread), hence, the /y/ in the child class simply stays mutable. The /z/ will stay a *val* (immutable) because its parent declaration is defined as such. class Point { final public float val $x = 0.0; final public float val $y = 0.0; } final class Point3d extends Point { final public float val $z = 0.0; } final class MutablePoint extends Point { final public float var $x; // FATAL ERROR final public float var $y; // FATAL ERROR } The *final* keyword could be added via another RFC and it would have the same meaning as the *final* keyword for classes and methods: freeze the definition. This is why the *MutablePoint* results in fatal errors: it tries to redeclare /x/ and /y/ from *val* to *var* although they are *final*. Note that this could be easily extended to local variables at a later stage as well and it would be extremely useful. I think that Scala's *val*/*var* approach could really help us to make *var* usable again in a meaningful manner and it corresponds nicely to the concept of /value objects/ and related concepts with its naming scheme. What do you think?
-- Richard "Fleshgrinder" Fussenegger

Stas Malyshev

10 years ago
Hi!
> The *var* keyword is not going to be deprecated and its meaning is > currently kind of ambiguous. I tried to assign it a new meaning in > the
Why is it ambiguous? It's pretty well defined, it's the same as public.
> class Foo { > > val $x; > > var $y; > > val $z; > > } > > class Bar extends Foo { > > var $x; > > $y; > > $z; > > }
This looks very unobvious what is supposed to be going on here. I'd much prefer to have every specification be explicit.
> The /z/ will stay a *val* (immutable) because its parent > declaration is defined as such. > > class Point { > > final public float val $x = 0.0;
Wait, how is this different from a constant?
> The *final* keyword could be added via another RFC and it would > have the same meaning as the *final* keyword for classes and > methods: freeze the definition. This is why the *MutablePoint* > results in fatal errors: it tries to redeclare /x/ and /y/ from > *val* to *var* although they are *final*.
I'm not sure I understand what is the point in freezing the definition. Could you explain use case for such thing?
> I think that Scala's *val*/*var* approach could really help us to > make *var* usable again in a meaningful manner and it corresponds > nicely to the concept of /value objects/ and related concepts with > its naming scheme.
I'm not sure why var is unusable and why it is a worthy goal to make it "usable again" - i.e. what exactly we are trying to achieve here? If we want value objects, it *might* be valuable to have an object that is readable but not writable from outside - even though it is easily achievable right now by having public getters but no public setters. But I'm not sure how "var" - or, for that matter, "final" - fits the picture.
-- Stas Malyshev smalyshev@gmail.com

Fleshgrinder

10 years ago
On 4/13/2016 6:42 AM, Stanislav Malyshev wrote:
> Hi! > >> The *var* keyword is not going to be deprecated and its meaning is >> currently kind of ambiguous. I tried to assign it a new meaning in >> the > > Why is it ambiguous? It's pretty well defined, it's the same as public. >
Well, no. The differences are well explained in the deprecation RFC: https://wiki.php.net/rfc/var_deprecation The documentation states the *var* is a substitute for *public* but in reality it isn't. Also the name is ambiguous because /var/ does not mean /public/. ;) On 4/13/2016 6:42 AM, Stanislav Malyshev wrote:
>> class Foo { >> >> val $x; >> >> var $y; >> >> val $z; >> >> } >> >> class Bar extends Foo { >> >> var $x; >> >> $y; >> >> $z; >> >> } > > This looks very unobvious what is supposed to be going on here. I'd > much prefer to have every specification be explicit. >
This was less a proposal regarding how it will be in userland and more about how the inheritance should be. I fully and completely agree with you that the full definition should be restated if a property is going to be redeclared in a child in userland. Either 1:1 or by changing what is allowed to change. The above example in userland with a more realistic example would be: class Foo { public float val $x; public float val $y; } class Bar extends Foo { public float var $x; public float var $y; } On 4/13/2016 6:42 AM, Stanislav Malyshev wrote:
>> The /z/ will stay a *val* (immutable) because its parent >> declaration is defined as such. >> >> class Point { >> >> final public float val $x = 0.0; > > Wait, how is this different from a constant? >
It is different to a constant in many ways: - It is bound to the instance and GCed with it. - It can be set in the constructor. - It can be cloned in __clone. Of course there are other added benefits of properties like the ability to contain object instances while not being reassignable but internally mutable. Again, the example was more about how things should work and not meant to be useful in any context. Here is a better example, however, some compromises with non-final class and property visibility to illustrate features: class Entity { final public int val $id; final public DateTimeImmutable val $created; final protected DateTimeImmutable var $changed; final protected OtherEntity var $other_entity; public function __construct( int $id, DateTimeImmutable $created, DateTimeImmutable $changed, OtherEntity $other_entity ) { assert( '$created <= $changed', '`created` cannot be less than `changed`' ); $this->id = $id; $this->created = $created; $this->changed = $changed; $this->other_entity = $other_entity; } public function __clone() { $this->other_entity = clone $this->other_entity; } public function getChanged(): DateTimeImmutable { return $this->changed; } public function update(): void { $this->changed = new DateTimeImmutable; } On 4/13/2016 6:42 AM, Stanislav Malyshev wrote:
>> The *final* keyword could be added via another RFC and it would >> have the same meaning as the *final* keyword for classes and >> methods: freeze the definition. This is why the *MutablePoint* >> results in fatal errors: it tries to redeclare /x/ and /y/ from >> *val* to *var* although they are *final*. > > I'm not sure I understand what is the point in freezing the > definition. Could you explain use case for such thing? >
To avoid that child classes change the signature of a property from a parent class if that is not desired. This is especially useful if you intend to use public properties as part of your API or simply want to update an existing anemic domain model by slowly adding the newly proposed features here and to find bugs (e.g. assignments of wrong data types, assignments at all, ...). I am not saying that public properties should be part of an API. As I wrote already and as Larry Garfield pointed out, having them as part of the public API would mean that interfaces should be able to declare them and that classes should be able to implement hooks. In other words: https://wiki.php.net/rfc/propertygetsetsyntax-v1.2 @Larry: I know that I wrote that I don't get why you brought up that RFC but now I know (and why I wrote a short addendum mail). ;) On 4/13/2016 6:42 AM, Stanislav Malyshev wrote:
>> I think that Scala's *val*/*var* approach could really help us to >> make *var* usable again in a meaningful manner and it corresponds >> nicely to the concept of /value objects/ and related concepts with >> its naming scheme. > > I'm not sure why var is unusable and why it is a worthy goal to make > it "usable again" - i.e. what exactly we are trying to achieve here? >
For the reasons mentioned at the top and in the thread where we discussed the deprecation. :)
> If we want value objects, it *might* be valuable to have an object > that is readable but not writable from outside - even though it is > easily achievable right now by having public getters but no public > setters. But I'm not sure how "var" - or, for that matter, "final" - > fits the picture. >
I hope I was able to explain the *var*, *val*, and *final* idea and I encourage you to check out Java, Scala, Ceylon, ... Immutable classes were discussed too in the not so far past and they would add a lot of benefit but other benefits. The main advantage would be that the objects could be considered safe at runtime for concurrency (not a feature we currently have in PHP but still holds true) and would not require one to take care of copy on write all the time. class ValueObject { private $value; public function __construct($value) { $this->value = $value; } public function doSomething() { $clone = clone $this; $clone->value = 'did something'; return $clone; } } Here is the related discussion that we should keep alive: http://marc.info/?t=144766539400001&r=1&w=2
-- Richard "Fleshgrinder" Fussenegger