Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:123536 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id AC8D61A009C for ; Fri, 7 Jun 2024 12:46:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1717764441; bh=ByRsOrNUkpKFJ2uo1Tbp1VdHwoYD3MTHj26kNnLHFV0=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=j5aqUkNJMSGg29ixmyK9qs2gEkby4N4Rv7rurIbn7CUP8Fuh/yFK0cfrkSIXv0tJ6 stMIm4PSz9IKjsOd38+pbFO99DoCpRxI2P5XPYBTh9aBQcvXbF+CiVWSNkJfLuuvXh s3VfE4dL2L+VlWtoanXmz20d5j5HOrZMpgJr19NhrfDxW0e7sLqI3pfJjlc+eHyjzi V88/+TRXrwS5buNXEuN+Aw1y0UdX+MW62zZmXJN7s92K36F2YrKNVsoBk4Dw4lh3jT E6knCoEpxLJSM6oYUfMwtmV89EMOr4a9E3CABRBGqlhPJZJXzoeB8KakCa5A+44TtJ nUxohJcdpA2qw== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 32024180039 for ; Fri, 7 Jun 2024 12:47:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: Error (Cannot connect to unix socket '/var/run/clamav/clamd.ctl': connect: Connection refused) X-Envelope-From: Received: from mail-lj1-f176.google.com (mail-lj1-f176.google.com [209.85.208.176]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 7 Jun 2024 12:47:19 +0000 (UTC) Received: by mail-lj1-f176.google.com with SMTP id 38308e7fff4ca-2e6f2534e41so22225521fa.0 for ; Fri, 07 Jun 2024 05:46:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1717764372; x=1718369172; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=lxgshfYAUk7vaF6196Qp3GPeLjpRh8SxGFfw2NezlrE=; b=DHN7j+nzHUX9nR5rTBdVDALhUJfLyeVROMVzJ31gRcRVMb3JYudTD/UtJ2WuzyDWSb IWF1jel7bnf5iPO7JOYI1ecMRp0XeLXfCCAFkP0aQlQDwGtwgicsCSsbL1fGRokQndO5 4AFTG5g8ol9dOnu3pnZ7s16k7DkHSiZmW82Ho7Mn9lRP8SE1LKAbCC+GddOXFrgyIvVU ikCoeb+iOrGlvw4Oh1VkVrKXXrUn7D1i5QpikRVXSx4zZtW94ImqF/ZOkJbpEJ6fSpiF FnEJb7I4vckPKMQ3bYFYG3npYmWSN7CMQgM3SyHva+pYuQYWKiUdnCEcdgZxN03+RIQg laLw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1717764372; x=1718369172; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=lxgshfYAUk7vaF6196Qp3GPeLjpRh8SxGFfw2NezlrE=; b=UHGOL76f3MpeY9qJj4uWgXYgdu72yLKwfeuK05vWFSWuIVSIA4vsJwEZAuzjO+ucqA MjvwyYn9ghx7eN6NVEXS9XqEFO32RNqs0+Wm/sQl2wadMQtRR+YGlUnax6x+J6nmaAlu aO6GaAJPW53kRSHQk5PjCb8ViCIQKALEw2vOnn8n/XoFvNkBJAog6V5p2rlZMvOYET+M 9vesPsnF2kYWVu7AcuUAve6dH1YoWGDM24Bd8NgoESBCfdvKJrXqZL5LnlY3ivqDLDR+ 3JPNQAudtNuHATc9qpg5YYd3fy1OMpl8DXOBR9NBhVh1NKW3aLVHH+/VQCDnZpL1u7lk yUQA== X-Gm-Message-State: AOJu0YzDHu0UysFLekjfwoViXgi79xGCjPsxSxpWvegRicy/6qYns40w g4g+RoWaVfHnALY8s9hsVFWgGjtbq0wgiKcuVYMTT6lLEb/xnetPGuWpPPmBN+AVgHi3JuxLFsA L7Bvon2cGCeoX2FU8I7WadUyeYw== X-Google-Smtp-Source: AGHT+IGryJd+7ysGz5rLP0JzgSqfn64qlHDvwYq5pKYHhudfDh2XSZwilSMfBerSWsuqFG1RX2HjSetR7n57afOGda8= X-Received: by 2002:a2e:2d01:0:b0:2ea:85f0:9165 with SMTP id 38308e7fff4ca-2eadce35604mr16141911fa.19.1717764371900; Fri, 07 Jun 2024 05:46:11 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net MIME-Version: 1.0 References: In-Reply-To: Date: Fri, 7 Jun 2024 15:46:00 +0300 Message-ID: Subject: Re: [PHP-DEV] Default value for readonly properties To: Claude Pache Cc: php internals Content-Type: multipart/alternative; boundary="00000000000031f2cb061a4c2fd5" From: udaltsov.valentin@gmail.com (Valentin Udaltsov) --00000000000031f2cb061a4c2fd5 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Friday, 7 June 2024=E2=80=AFat 12:11, Claude Pache wrote: > Hi, > > As of today, readonly properties cannot have a default value: > > ```php > class UltimateQuestion { > readonly int $answer =3D 42; // Fatal error: Readonly property > Question::$answer cannot have default value > } > ``` > > The rationale given in the original RFC ( > https://wiki.php.net/rfc/readonly_properties_v2) was: > > As the default value counts as an initializing assignment, a readonly > property with a default value is essentially the same as a constant, and > thus not particularly useful. The notion could become more useful in the > future, if new expressions are allowed as property default values. At the > same time, depending on how exactly property initialization would work in > that case, having a default value on a readonly property could preclude > userland serialization libraries from working, as they would not be able = to > replace the default-constructed object. Whether or not this is a concern > depends on whether the property is initialized at time of object creation= , > or as an implicit part of the constructor (or similar). As these are open > questions, the conservative choice is to forbid default values until thes= e > questions are resolved. > > A new fact is that properties will be able to be declared in interface > since PHP 8.4 (as introduced in the recently accepted property hooks RFC)= . > It is true that, for an individual class, a readonly property is > functionally equivalent to a constant. But my class implements an interfa= ce > (or, before 8.4, follows a non-written protocol), and whether that > particular implementation choose to always hold the same value for a > specific property is irrelevant. > > > ```php > interface Question { > public int $answer { get; } > } > class UltimateQuestion implements Question { > readonly int $answer =3D 42; > } > ``` > > Therefore I think it is reasonable for readonly properties to accept > default values. > > About the concern given in the original RFC: =E2=80=9Chaving a default va= lue on a > readonly property could preclude userland serialization libraries from > working, as they would not be able to replace the default-constructed > object=E2=80=9D... TBH, as I almost never serialise my objects, and even = less often > customise serialisation, I can only guess what the effective issue is. My > best guess is that a custom `__unserialize()` method would not be able to > reinstate the incriminated readonly properties, because those would alrea= dy > have been initialised with the default value. If this is the case, a > solution is to do for `__uninitialize()` the same thing that we have done > for `__clone()`, see: > https://wiki.php.net/rfc/readonly_amendments#proposal_2readonly_propertie= s_can_be_reinitialized_during_cloning > > =E2=80=94Claude > Hi, Claude! Thank you for bringing up this issue! I agree that the phrase "a readonly property with a default value is essentially the same as a constant" is not correct for all cases. For example, I might have a class like this: ```php final readonly class ObjectCollector { private SplObjectStorage $storage; public function __construct() { $this->storage =3D new SplObjectStorage(); } public function add(object $object): void { $this->storage->attach($object); } } (new ObjectCollector())->add(new stdClass()); ``` It's a fully working example (https://3v4l.org/dSpQO) where `$storage` can not be replaced with a constant. And it would be nice if `$storage` could be initialized without a constructor. I just looked at some of my PHP >=3D8.1 projects and noticed that I have a few places where the constructor has no parameters and only exists to initialize readonly properties with smth like `SplQueue`. --=20 Valentin Udaltsov --00000000000031f2cb061a4c2fd5 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
On Friday, 7 June 2024=E2=80=AFat 12:11, = Claude Pache <claude.pache@gmail.com> wrote:
Hi,

<= div>As of today, readonly properties cannot have a default value:

```php
class UltimateQuestion {
= =C2=A0 =C2=A0 readonly int $answer =3D 42; //=C2=A0Fatal error: Readonly pr= operty Question::$answer cannot have default value
}
<= div>```

The rationale given in the original RFC (<= a href=3D"https://wiki.php.net/rfc/readonly_properties_v2" target=3D"_blank= ">https://wiki.php.net/rfc/readonly_properties_v2) was:

<= /div>
=
As the default value counts as an initializing assignment, a readonly = property with a default value is essentially the same as a constant, and th= us not particularly useful. The notion could become more useful in the futu= re, if new expressions are allowed as property default values. At the same = time, depending on how exactly property initialization would work in that c= ase, having a default value on a readonly property could preclude userland = serialization libraries from working, as they would not be able to replace = the default-constructed object. Whether or not this is a concern depends on= whether the property is initialized at time of object creation, or as an i= mplicit part of the constructor (or similar). As these are open questions, = the conservative choice is to forbid default values until these questions a= re resolved.

A new fact is that properties= will be able to be declared in interface since PHP 8.4 (as introduced in t= he recently accepted property hooks RFC). It is true that, for an individua= l class, a readonly property is functionally equivalent to a constant. But = my class implements an interface (or, before 8.4, follows a non-written pro= tocol), and whether that particular implementation choose to always hold th= e same value for a specific property is irrelevant.


=
```php
interface Question {
public int $answer { get; }
}
class UltimateQuestion implements Question {
=C2=A0= =C2=A0 readonly int $answer =3D 42;
}
```
<= /div>

Therefore I think it is reasonable for readonly pr= operties to accept default values.

About the conce= rn given in the original RFC: =E2=80=9Chaving a default value on a readonly= property could preclude userland serialization libraries from working, as = they would not be able to replace the default-constructed object=E2=80=9D..= . TBH, as I almost never serialise my objects, and even less often customis= e serialisation, I can only guess what the effective issue is. My best gues= s is that a custom `__unserialize()` method would not be able to reinstate = the incriminated readonly properties, because those would already have been= initialised with the default value. If this is the case, a solution is to = do for `__uninitialize()` the same thing that we have done for `__clone()`,= see: htt= ps://wiki.php.net/rfc/readonly_amendments#proposal_2readonly_properties_can= _be_reinitialized_during_cloning

=E2=80=94Clau= de

Hi,=C2=A0Claude!
Thank you for bringing up this issue! I agree that the phrase "a = readonly property with a default value is essentially the same as a constan= t" is not correct for all cases. For example, I might have a class lik= e this:

```php
final readonly class ObjectCollector
{
=C2= =A0 =C2=A0 private SplObjectStorage $storage;

=C2=A0 =C2=A0 public f= unction __construct()
=C2=A0 =C2=A0 {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 $th= is->storage =3D new SplObjectStorage();
=C2=A0 =C2=A0 }

=C2=A0= =C2=A0 public function add(object $object): void
=C2=A0 =C2=A0 {
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 $this->storage->attach($object);
=C2=A0 = =C2=A0 }
}

(new ObjectCollector())->add(new stdClass());
``= `

It's a fully working example (https://3v4l.org/dSpQO) where `$= storage` can not be replaced with a constant. And it would be nice if `$sto= rage` could be initialized without a constructor.

I just look= ed at some of my PHP >=3D8.1 projects and noticed that I have a few plac= es where the constructor has no parameters and only exists to initialize re= adonly properties with smth like `SplQueue`.
--
Valentin Udaltsov
--00000000000031f2cb061a4c2fd5--