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
signature.asc
Description: OpenPGP digital signature