Re: [RFC] [PROPOSAL] Immutable/final/readonly properties
| From: | Larry Garfield | Date: | Sat, 15 Feb 2020 08:18:15 +0000 |
| Subject: | Re: [RFC] [PROPOSAL] Immutable/final/readonly properties | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-108592@lists.php.net to get a copy of this message | ||
On Fri, Feb 14, 2020, at 7:22 AM, Máté Kocsis wrote:
> Hi Internals,
>
> I'd like to propose the idea of adding support for immutable/final/readonly
> properties in PHP 8.
>
> My plan is to add a new immutable/final/readonly (the name is up for
> debate) property modifier to the language so that these kind of properties
> could only be initialized but not modified afterwards. Unlike how final
> properties in Java work, I think it would be beneficial to allow lazy
> initialization of these properties after object construction have taken
> place. Currently, I'm in favour of using final or readonly, but not yet
> very sure.
>
> I'll write a proper RFC in the following days/week. My clear intent with
> final properties is to pave the road for immutable objects for which I have
> a POC pull request open (but I haven't pushed all my work yet).
>
> So far, my biggest question (apart from the name) have been how non-typed
> properties should behave: as they are implicitly initialized to null if
> they don't have an explicit default value (while typed properties remain
> uninitialized), further modifications would be impossible to do on them -
> which would make non-typed final properties almost useless. Nikita
> suggested to just avoid their initialization, but I'd be curious about
> other ideas as well.
>
> Thanks,
> Máté Kocsis
My concern is that a simple read-only/final "flag" is a very limited feature set.
I'd still love for us to revisit property accessors at some point (if the performance issues
could be resolved), and I fear that layering that *and* a read-only flag together would result in...
much complex weirdness. (Technical term.)
That said, were such a feature to be added, I would strongly recommend making them able to be
defined in terms of an expression, or possibly a callable/anon function, with no explicit setting
allowed. To wit:
class Foo {
protected string $firstName;
protected string $lastName;
protected function getFullName() { return $this->firstName . $this->lastName; }
// And then one of these options:
public final string $fullName = $this->firstName . $this->lastName;
public final string $fullName = fn() => $this->firstName . $this->lastName;
public final string $fullName = $this->getFullName();
}
That would allow for their complete definition in one location, make it clear how they're
derived, etc. They essentially become an auto-memoizing method (which suits me just fine). Their
value would potentially change depending on when it's first called depending on the other
values in the object, but that's no different than if they were simply "set" from an
arbitrary location. The potential for unpredictable semi-non-determinism is the same, or possibly
better this way.
(In that case, "final" or "lazy" or "locked" would be reasonable
names; read-only and immutable are misleading, as it's really write-once, not read-only, not
truly immutable. I suppose then an "immutable object" would be one in which all
properties are either final/lazy/locked or set by the constructor only.)
There was a thread a few weeks ago on "lazily derived constants" that probably has some
interesting thoughts as well, though of course this would be property-like syntax, which is fine.
As for references and untyped final properties... Just don't go there. Require a final
property to be non-reference and typed. I do not foresee untyped properties ever going away (too
much legacy code, plus they are legit useful at times), but that doesn't mean every conceivable
property variant ever needs to support them. Requiring that a final property be typed non-reference
seems entirely reasonable to me.
--Larry Garfield