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)
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
, orimmutable
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
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)
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:
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
, orimmutable
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 lineCheers,
Marco Pivetta
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)
Hi,
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 opinionimmutable
is object behavior when using
some methods you receive newly created (cloned) object which is changed
exactly likeDateTimeImmutable
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
, orimmutable
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 lineCheers,
Marco Pivetta
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
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 opinionimmutable
is object behavior when using
some methods you receive newly created (cloned) object which is changed
exactly likeDateTimeImmutable
http://php.net/manual/en/datetimeimmutable.add.phpI am aware of what
final
means in other languages, it just seems that
everyone then needs to translate back and forth fromfinal
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
, orimmutable
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 lineCheers,
Marco Pivetta
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 runtimebut 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 namedfinal
, 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
Cheers,
Michał Brzuchalski (aka brzuchal)
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/12ebda1efed59440a78ba43bff116728It 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 opinionimmutable
is object behavior when
using
some methods you receive newly created (cloned) object which is changed
exactly likeDateTimeImmutable
http://php.net/manual/en/datetimeimmutable.add.phpI am aware of what
final
means in other languages, it just seems that
everyone then needs to translate back and forth fromfinal
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 usedfinal
.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
, orimmutable
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
lineCheers,
Marco Pivetta
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
runtimebut 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 namedfinal
, 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
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.
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
/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):
- immutable for the functionality you are currently working on.
- sealed for the above plus type not changeable.
- 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
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 opinionimmutable
is object behavior when using
some methods you receive newly created (cloned) object which is changed
exactly likeDateTimeImmutable
http://php.net/manual/en/datetimeimmutable.add.phpI am aware of what
final
means in other languages, it just seems that
everyone then needs to translate back and forth fromfinal
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
...
(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
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
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
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
, orimmutable
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".
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
, orimmutable
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?
Another possible choice would be "readonly".
Am 09.04.2016 um 12:55 schrieb Niklas Keller:
Another possible choice would be "readonly".
Rather "writeonce", no?
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:
Am 09.04.2016 um 12:55 schrieb Niklas Keller:
Another possible choice would be "readonly".
Rather "writeonce", no?
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...
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:
Am 09.04.2016 um 12:55 schrieb Niklas Keller:
Another possible choice would be "readonly".
Rather "writeonce", no?
I would prefer putting the "final" keyword before the "public".
final public $items;
Since we should emphasis "final" rather than "public"
/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
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
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
theWhy 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/. ;)
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;
}
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;
}
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). ;)
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
Hi!
Well, no. The differences are well explained in the deprecation RFC:
"var is currently a simple alias for public. "
The documentation states the var is a substitute for public but in
reality it isn't.
How exactly it isn't? Except for "static"/"const" thing (which is really
a parser glitch and could be easily fixed if anybody cared) I don't see
a difference. Pretending like that static/const thing is a serious issue
that warrants some deep changes makes no sense to me - it's just a very
minor bug.
It is different to a constant in many ways:
- It is bound to the instance and GCed with it.
Don't see why is it good or why should I care.For all I care it may
never be GCed at all (such as interned strings), and userland developer
should not be worrying about these details anyway.
- It can be set in the constructor.
- It can be cloned in __clone.
I find the idea that you have special methods that have magic about
variables not available to other methods rather unwise. And, you forgot
__wakeup for example, unless you're not going to ever serialize your
value object. And maybe other use cases. The point is, you are building
very complex mechanism here that is too magic, and it is going to break
in weird ways because it doesn't work like the rest of language works.
It also promotes bad design, as unless you want to track stack traces,
you'd be able to touch these vars only in magic methods, thus requiring
placing the code dealing with these vars in each of those methods and
only there - you can't put this code in a different method, for example,
because that method won't be magic. So, no refactoring for magic methods.
public function update(): void { $this->changed = new DateTimeImmutable; }
I don't see how $created works better than $changed. Moreover, it looks
rather strange that you have getter for $changed but not for $created.
To achieve consistency and avoid confusing people, you probably would
also have getCreated() anyway - which then makes "val" completely redundant.
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
I think that's not how it is done by all code I've seen so far - they
use getters instead. Now, we can say we want to get rid of getters, but
then I still don't see what use case final serves. I mean, "final is to
make things unchangeable" is not a use case - it just restating the same
thing in different words. The real question is why you need to make
them unchangeable?
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:
Exactly. So, unless we implement tons of other things, you can't really
use it, and even then it's unclear why you want to use it.
For the reasons mentioned at the top and in the thread where we
discussed the deprecation. :)
Well, I see no real reason there and deprecation failed, as it should
have. I don't exactly buy the argument of "we tried to deprecate var,
unsuccessfully, therefore there is a problem with it", and the only real
issue I have seen, as I mentioned above, is that minor static/const
glitch.
I hope I was able to explain the var, val, and final idea and I
encourage you to check out Java, Scala, Ceylon, ...
I know about existence of Java, Scala, etc. but "look at Java" is not a
very good explanation - Java is big, so it would be useful to clarify
what exactly I am supposed to be looking at and how it should convince
me with regard to PHP.
Also, I remind that both Java and Scala are compiled fully statically
strict typed languages, and PHP is not.
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
Which is completely useless for PHP as it does not have
shared-environment concurrency and most likely never will. Also,
experience shows immutable value objects, while nice, does not solve
much of concurrency problems. Data structures are the real problem, and
immutable data structures are way harder to do. Anyway, this is
irrelevant for PHP in any case.
(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.
Err, how? The objects may be immutable but that says nothing of the
values within. So you'd still have to track them.
You could theoretically make some performance gains, maybe, by caching
property lookups, etc. for immutable objects, but I don't think you'd
gain too much compared to what we have now.
Stas Malyshev
smalyshev@gmail.com
How exactly it isn't? Except for "static"/"const" thing (which is really
a parser glitch and could be easily fixed if anybody cared) I don't see
a difference. Pretending like that static/const thing is a serious issue
that warrants some deep changes makes no sense to me - it's just a very
minor bug.
Possible approach, yes. Still a huge inconsistency with function
declarations and their access modifiers (var function?!?). Just look
at the special definitions in the Bison file on how it is currently
handled. I know that the two of us have a different meaning about this
topic but in case we extend access modifiers inconsistency grows.
var class ?!?
var function ?!?
var const ?!?
var static ?!?
It is different to a constant in many ways:
- It is bound to the instance and GCed with it.
Don't see why is it good or why should I care.For all I care it may
never be GCed at all (such as interned strings), and userland developer
should not be worrying about these details anyway.
I did not say that a userland developer should care I only stated that
it is one difference between a constant and a final property. ;)
- It can be set in the constructor.
- It can be cloned in __clone.
I find the idea that you have special methods that have magic about
variables not available to other methods rather unwise. And, you forgot
__wakeup for example, unless you're not going to ever serialize your
value object. And maybe other use cases. The point is, you are building
very complex mechanism here that is too magic, and it is going to break
in weird ways because it doesn't work like the rest of language works.
This thread is meant to find out where, how, when support is needed and
you are absolutely right that __wakeup needs support too. I am sure we
overlooked others yet. I did not claim to cover all edge cases. ;)
It also promotes bad design, as unless you want to track stack traces,
you'd be able to touch these vars only in magic methods, thus requiring
placing the code dealing with these vars in each of those methods and
only there - you can't put this code in a different method, for example,
because that method won't be magic. So, no refactoring for magic methods.
That is exactly the point of it. Limiting interaction, limiting sources
of bugs. Just read why others want to have them instead of only taking
my word (and bad examples) for it.
public function update(): void { $this->changed = new DateTimeImmutable; }
I don't see how $created works better than $changed. Moreover, it looks
rather strange that you have getter for $changed but not for $created.
To achieve consistency and avoid confusing people, you probably would
also have getCreated() anyway - which then makes "val" completely redundant.
It is an example to illustrate the functionality and not meant to be a
blueprint for all userland implementations that are yet to be written
till the end of time. It is contrived, no argument there.
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 toI think that's not how it is done by all code I've seen so far - they
use getters instead. Now, we can say we want to get rid of getters, but
then I still don't see what use case final serves. I mean, "final is to
make things unchangeable" is not a use case - it just restating the same
thing in different words. The real question is why you need to make
them unchangeable?
Because you want to let child classes read from the property without
calling methods while making sure that they cannot change it in any way
(also called readonly in C#). This is particularly important in case
of object getters because a child class cannot trust the parent class
that an object retrieved from that getter is always the same instance.
This is why it is recommended to assign the result of such a call in a
method in various highly regarded literature (e.g. Steve McConnell Code
Complete comes to my mind).
With a final val property the child can trust the parent again. I know
that the situation is often different in PHP because the source is
always readily available. However, an API user should not need to dig
into the source code, an API user should be able to understand, use, and
trust other code simply through peeking at definitions and signatures.
Before you start, I am not claiming that this is always possible nor
that this is always desired, always needs to be like that, or anything
else. It is just something that is nice to achieve and it allows control
over what is going to happen at runtime and how people will be able to
interact with code that was written by you for them.
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:Exactly. So, unless we implement tons of other things, you can't really
use it, and even then it's unclear why you want to use it.
Public properties are available yet and used heavily in many projects to
create shitty anemic domain model for, you guessed it, performance
reasons. Providing a final keyword will not change that. Larry just
brought up the discussion regarding properties in interfaces, that's it
and nothing more.
For the reasons mentioned at the top and in the thread where we
discussed the deprecation. :)Well, I see no real reason there and deprecation failed, as it should
have. I don't exactly buy the argument of "we tried to deprecate var,
unsuccessfully, therefore there is a problem with it", and the only real
issue I have seen, as I mentioned above, is that minor static/const
glitch.
I know that it might look like that but I still think that its usage is
ambiguous and inconsistent and all explanation attempts failed in the
old thread, in the RFC, and they will fail here. I do not know any other
way in that I could explain it to you so that you agree. However, I do
not know of I have to be that person who does that. It's fine for me if
you are against it or me. :)
I hope I was able to explain the var, val, and final idea and I
encourage you to check out Java, Scala, Ceylon, ...I know about existence of Java, Scala, etc. but "look at Java" is not a
very good explanation - Java is big, so it would be useful to clarify
what exactly I am supposed to be looking at and how it should convince
me with regard to PHP.
Also, I remind that both Java and Scala are compiled fully statically
strict typed languages, and PHP is not.
Really? You should look at final, val, and var -- what are we
discussing here?
https://en.wikipedia.org/wiki/Final_%28Java%29
http://www.scala-lang.org/files/archive/spec/2.11/04-basic-declarations-and-definitions.html
http://stackoverflow.com/a/1327549/1251219
would add a lot of benefit but other benefits. The main advantage would
be that the objects could be considered safe at runtime for concurrencyWhich is completely useless for PHP as it does not have
shared-environment concurrency and most likely never will. Also,
experience shows immutable value objects, while nice, does not solve
much of concurrency problems. Data structures are the real problem, and
immutable data structures are way harder to do. Anyway, this is
irrelevant for PHP in any case.
I said so and it was only an example. However, people are actually
trying (pthreads? anyone?) to bring this to PHP so never say never. ;)
(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.Err, how? The objects may be immutable but that says nothing of the
values within. So you'd still have to track them.
You could theoretically make some performance gains, maybe, by caching
property lookups, etc. for immutable objects, but I don't think you'd
gain too much compared to what we have now.
You gain a shitload of DRY in userland. This is more than worthwhile.
You might react allergic towards syntactic sugar but it can be extremely
nice. But let's not get off-topic any further here (feel free to open
separate threads or resurrect the old one, I will reply).
--
Richard "Fleshgrinder" Fussenegger
Hi!
var class ?!?
var function ?!?
var const ?!?
var static ?!?
Ah, of course not. "var" is for vars.
I did not say that a userland developer should care I only stated that
it is one difference between a constant and a final property. ;)
This is not a difference that is important.
This thread is meant to find out where, how, when support is needed and
you are absolutely right that __wakeup needs support too. I am sure we
overlooked others yet. I did not claim to cover all edge cases. ;)
Part of my point is that covering the edges would be hard, because you
are trying to introduce something that is not aligned with how the
language is (or was) supposed to work, and thus require a lot of special
cases. This is a sure recipe for trouble - once you rely on
special-casing, you are guaranteed to forget some. KISS was not
proclaimed a principle just because people are lazy and avoid work.
That is exactly the point of it. Limiting interaction, limiting sources
of bugs. Just read why others want to have them instead of only taking
my word (and bad examples) for it.
But it's not limiting - you can not even refactor methods, so you'd have
to copy-paste same code in several methods, with all bugs that follow.
And of course you'd frequently forget to account for all places where
magic should happen and get objects behaving in weird ways. This does
not sound good.
I can see a case between splitting read and write on class boundary -
internal implementation can write, but outside can only read. In fact,
this pattern is already widely implemented. I can see why you may want
to get rid of this pattern of having interface/getter and instead have a
pattern of public variables - but for this you'd need property
interfaces first, and even then it would be unclear - how exactly the
interface would specify readonly variable? Would you be allowed to
extend it with r/w variable (I can give you equally sound arguments for
"yes" and "no" here, depending on use case)?
With getters/setters, the answer is clear - yes, you can extend it with
setters, but if your invariant relies on immutability, you'd be
violating LSP. With properties, not clear.
It also seems to me like the main reason to do this is to exactly mimick
behavior of "final" properties in Java - which is not a very worthy goal
by itself.
It is an example to illustrate the functionality and not meant to be a
blueprint for all userland implementations that are yet to be written
till the end of time. It is contrived, no argument there.
The problem is not that it's contrived, the problem is that it shows not
why you need it but rather why you don't need it :) You are welcome to
provide better example/use case, of course, but so far it looks to me
like protected/getter works just fine. At the cost of a function call,
of course, but see above why it may be preferable.
Because you want to let child classes read from the property without
calling methods while making sure that they cannot change it in any way
(also called readonly in C#). This is particularly important in case
You can always have private/protected as boundary instead of
protected/public, that doesn't change much. Saving a function call looks
like premature optimization here.
of object getters because a child class cannot trust the parent class
that an object retrieved from that getter is always the same instance.
Not sure what you mean here. If the API allows to return different
instances, then you get different instances. What's the problem here?
With a final val property the child can trust the parent again. I know
This looks like wrong design approach - you are trying to put knowledge
on the client that does not belong there - such as how many instances of
value object exist and how they are managed. For value objects this
looks wrong - if it's a value, it shouldn't matter which instance of it
you are getting. If it's a mutable stateful object and not a value
object, it's worse - you can't then know who messed with that object
before and what is there now, so final doesn't help much.
I know that it might look like that but I still think that its usage is
ambiguous and inconsistent and all explanation attempts failed in the
Ambiguous between what and what? If you see "var $foo", which two
options you can not distinguish? How it is inconsistent? I think we need
to stop using "inconsistent" when that is meant is "I do not like it".
"var" is perfectly consistent and means always the same thing. There's
better named alternative for it, true, and you're free to use that if
you like. That's it.
Really? You should look at final, val, and var -- what are we
discussing here?
"final" in Java is used in a lot of senses. Some of them would make
sense in PHP, some not. For some cases, "final" doesn't actually provide
much value - e.g. assigning a mutable object to a final variable, since
it does not guarantee you anything really except keeping reference.
There are a lot of optimizations that final is targeted for in Java, but
I'm not sure those same optimizations are even possible in PHP. May be
worth exploring though.
Err, how? The objects may be immutable but that says nothing of the
values within. So you'd still have to track them.
You could theoretically make some performance gains, maybe, by caching
property lookups, etc. for immutable objects, but I don't think you'd
gain too much compared to what we have now.You gain a shitload of DRY in userland. This is more than worthwhile.
Sorry, I don't see it so far. I.e. I believe you think it'd be amazing,
but I'd rather see some example of how it would be amazing and not take
your word on it. Use cases are very important in design, in fact until
we've got good use cases we don't have good design.
You might react allergic towards syntactic sugar but it can be extremely
Oh, I'm not. But this is way beyond simple sugar, this is a bucketload
of concepts that never existed in PHP, and I'd like to see they work
with what does exist in PHP and they actually make sense for PHP, not
just copying something Java does word-for-word.
Stas Malyshev
smalyshev@gmail.com
With getters/setters, the answer is clear - yes, you can extend it with
setters, but if your invariant relies on immutability, you'd be
violating LSP. With properties, not clear.
So in summary preference would be that something like Property Accessors Syntax* is re opened and updated?
From user land main motivation to support this and typed properties is to be allowed to type hint and make properties readonly to simplify use cases for entities and value objects, using properties, and not having to resort to magic methods which tends to become slow(er) and messy. For how this is archived, not violating LSP, and making sure the language and internals are kept as consistent as possible would be high up there as reasoning to pick approach