Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126761 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 461391A00BC for ; Fri, 14 Mar 2025 18:46:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1741977852; bh=QoMJCeB3V4mHy0KNhjLmQt7ZjHi03AVT5layFtRobWA=; h=Date:From:To:In-Reply-To:References:Subject:From; b=IMQRh3nf5FXU1BQ/y4CdlJ7L3Qgcg3CXHu/2JVGw4E69E+M5q2layoccoVRAB0O3V ICjinIuhIRh/vob+4dDS8tvbw/X8D0BMp9CjbWyi3O/YbS0AxRbTLzpNrRPScdbQvh NMEUYh04jvBd75QMuH5jcCw29qh5yQVzfa3RNj6iLahLD7PwzVwuheVsFCwh59Qoy9 BpfTz38g5tlWbVIxx7eKImfF/jUmWKidbx5r0m0JC+RU7ah8HIiuU8hMdOrrIH1uo8 RvgfhTTbdeliUMk+IAn+aGcBMc0D54/bCKUkmyUbuGtJ7laEniEwo9gr9/pjbpCPmM X3JgN+iRDcayQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 11EA7180037 for ; Fri, 14 Mar 2025 18:44:11 +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=-2.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from fhigh-b3-smtp.messagingengine.com (fhigh-b3-smtp.messagingengine.com [202.12.124.154]) (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, 14 Mar 2025 18:44:10 +0000 (UTC) Received: from phl-compute-11.internal (phl-compute-11.phl.internal [10.202.2.51]) by mailfhigh.stl.internal (Postfix) with ESMTP id 35E112540140 for ; Fri, 14 Mar 2025 14:46:43 -0400 (EDT) Received: from phl-imap-09 ([10.202.2.99]) by phl-compute-11.internal (MEProxy); Fri, 14 Mar 2025 14:46:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bottled.codes; h=cc:content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm2; t=1741978003; x=1742064403; bh=rP7YJTpzHH 6CLgwoR0vCURxzHnIJLaRd4ARbBnl8FdQ=; b=cY7/rJrirvWyUNnv1BDDNXEMdw qYhgzEd8Pt+rEGbcyrHoCE8DgdTgTkthg5OLrQuNBDgzBjIYhFvG1rzJbr+L9LLd onpF7KMFanWviojWdXLmKdeTvI6m/9qAVDM/tBpZBQqUQB3bzgxlgqFXcYwZUtfD tJ+uZtf0FZGUXvXTu5sqoOQWb+3Q+GEke9iOpXPcUq66INJ7MILseCP7Kmy+sCfG gY9WeTmWodwJQHlyw4ousML9IcyEa3V6P43zUGn4Dud8zN3L2k5zSSJnh1aXyaww SLQPZOmHZR4fAE8HBQC3Ad/TG4f3I5Q0TzS4JO6GqHAIf+m9ZEUDzQha6lew== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t= 1741978003; x=1742064403; bh=rP7YJTpzHH6CLgwoR0vCURxzHnIJLaRd4AR bBnl8FdQ=; b=v/aQ7JlvX/sc6r6aNbNZzkJ491otrO2/QFylPu1MU25vMsCtaPL Tw9XnaYMZjE+RfSaNxABbsTqtgahm546AKCD8wna5paTQ2lDSIUd8Wv2YlETolkR 18KHBx8f6er39QPT6O4iZ9rpa95ArOVxCd9R13ss5rfR+u4bSK7+0qnEdYxUzqCL wpefCwmXXT8IP1QK9k3jE69wLnur4Oq/vixzzu4ltQUM/r96Qo+xLNWyi3IE5lF/ zhANKop7159GkXoCcFLnc4L7nStTeSsyr1KaHOk1RkbdNx1FECvolcQ5aJy5e0Np DorFT+zktYXJa3NLknsAEQYDQVICV6Cv51w== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddufeduheekucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggv pdfurfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucenucfjughrpefogg ffhffvkfgjfhfutgesrgdtreerredtjeenucfhrhhomhepfdftohgsucfnrghnuggvrhhs fdcuoehrohgssegsohhtthhlvggurdgtohguvghsqeenucggtffrrghtthgvrhhnpeehie ffkeetleejueefjeffueffheevudfgteevfeeijeevfffhhfegueetteffleenucffohhm rghinhepphhhphdrnhgvthdpghhithhhuhgsrdgtohhmnecuvehluhhsthgvrhfuihiivg eptdenucfrrghrrghmpehmrghilhhfrhhomheprhhosgessghothhtlhgvugdrtghouggv shdpnhgspghrtghpthhtohepuddpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtohepih hnthgvrhhnrghlsheslhhishhtshdrphhhphdrnhgvth X-ME-Proxy: Feedback-ID: ifab94697:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id A5713780068; Fri, 14 Mar 2025 14:46:42 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 Date: Fri, 14 Mar 2025 19:46:22 +0100 To: internals@lists.php.net Message-ID: <80a72934-fada-47a7-b35b-59a1c8704097@app.fastmail.com> In-Reply-To: <2935d0e2-ddc4-447c-ab37-c9b7337b8b60@app.fastmail.com> References: <2935d0e2-ddc4-447c-ab37-c9b7337b8b60@app.fastmail.com> Subject: Re: [PHP-DEV] Re: RFC: short and inner classes Content-Type: multipart/alternative; boundary=1ae25b4bb160418d8d482a5b3b72b6e2 From: rob@bottled.codes ("Rob Landers") --1ae25b4bb160418d8d482a5b3b72b6e2 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Wed, Mar 12, 2025, at 11:10, Rob Landers wrote: > On Thu, Mar 6, 2025, at 00:11, Rob Landers wrote: >> Hello PHP Internals, >>=20 >> I'd like to introduce my RFC for discussion: https://wiki.php.net/rfc= /short-and-inner-classes >>=20 >> This RFC defines a short class syntax as well as the ability to nest = classes inside another class. This introduces an unprecedented amount of= control, flexibility, and expressiveness over how objects are used and = instantiated in PHP. There is a PR (https://github.com/php/php-src/pull/= 17895) that implements this functionality -- all test failures are relat= ed to different/new/incorrect error messages being generated. However, t= he core functionality exists to take for a test ride. >>=20 >> So, what do I mean by "unprecedented amount of control"? With this ch= ange, you can declare an inner class as private or protected, preventing= its usage outside of the outer class: >>=20 >> class User { >> private class Id {} >>=20 >> public function __construct(public self::Id $id) {} >> } >>=20 >> In the above example, the class `User` is impossible to construct eve= n though it has a public constructor (except through reflection) because= User::Id is private; User::Id cannot be instantiated, used as a type hi= nt, or even via `instanceof` outside of the User class itself. This exam= ple isn't practical but demonstrates something that is nearly impossible= in previous versions of PHP, where all classes are essentially publicly= accessible from anywhere within the codebase. >>=20 >> As a number of inner classes will probably be used as DTOs, the RFC i= ntroduces a "short syntax" for declaring classes, which enhances express= iveness, even allowing the usage of traits, all in a single line: >>=20 >> // declare a readonly Point, that implements Vector2 and uses the Evo= lvable trait >> readonly class Point(public int $x, public int $y) implements Vector2= use Evolvable; >>=20 >> When combined with inner classes, it looks something like this: >>=20 >> class Pixel { >> public readonly class Point(public int $x, public int $y) implement= s Vector2 use Evolvable; >> } >>=20 >> // Create a new pixel point with property $x and $y set to 0 >> $p =3D new Pixel::Point(0, 0); >>=20 >> There are far more details in the RFC itself, so please check it out.= I'm quite excited to hear your thoughts! >>=20 >> =E2=80=94 Rob >>=20 >> PS. I know I tend to rush into things, but I want to make it clear th= at I'm not rushing this -- I've learned from my mistakes (thank you to t= hose who have given me advice). I'm going to do this right. >>=20 >>=20 >=20 > Hello internals, >=20 > I've made some major updates to the text of the RFC to clarify behavio= rs and revisited the implementation (which is still under development, t= hough I hope to have a draft by the end of this weekend). Here's a broad= overview of what has changed in inner classes: >=20 > - Accessing inner classes is done via a new token: ":>" instead of "::= ". > - Inner classes may now be infinitely nested. > - Inner classes may be declared `abstract`. > - Documented changes to ReflectionClass. > - Usage of `static` to refer to inner classes is restricted to prevent= accidental violations of LSP. >=20 > Otherwise, there are not any big changes, but a lot of time was spent = clarifying behavior and expanding on the reasoning for those decisions i= n the RFC itself. >=20 > =E2=80=94 Rob For those who are interested, I've opened the PR that enables this featu= re: https://github.com/php/php-src/pull/18069 =E2=80=94 Rob --1ae25b4bb160418d8d482a5b3b72b6e2 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable
On Wed, Mar = 12, 2025, at 11:10, Rob Landers wrote:
On Thu, Mar 6, 2025, at 00:11, Rob Landers w= rote:
He= llo PHP Internals,

I'd like to introduce my= RFC for discussion: https://wiki.php.net/rfc/short-and-inner-classes
<= /div>

This RFC defines a short class syntax as well a= s the ability to nest classes inside another class. This introduces an u= nprecedented amount of control, flexibility, and expressiveness over how= objects are used and instantiated in PHP. There is a PR (https://github.com/php/php-src/p= ull/17895) that implements this functionality -- all test failures a= re related to different/new/incorrect error messages being generated. Ho= wever, the core functionality exists to take for a test ride.
<= div>
So, what do I mean by "unprecedented amount of contro= l"? With this change, you can declare an inner class as private or prote= cted, preventing its usage outside of the outer class:
class User {
  private class Id {}

  public function __construct(public self::I= d $id) {}
}

In the above exam= ple, the class `User` is impossible to construct even though it has a pu= blic constructor (except through reflection) because User::Id is private= ; User::Id cannot be instantiated, used as a type hint, or even via `ins= tanceof` outside of the User class itself. This example isn't practical = but demonstrates something that is nearly impossible in previous version= s of PHP, where all classes are essentially publicly accessible from any= where within the codebase.

As a number of i= nner classes will probably be used as DTOs, the RFC introduces a "short = syntax" for declaring classes, which enhances expressiveness, even allow= ing the usage of traits, all in a single line:

<= div>// declare a readonly Point, that implements Vector2 and uses the Ev= olvable trait
readonly class Point(public int $x, public i= nt $y) implements Vector2 use Evolvable;

Wh= en combined with inner classes, it looks something like this:
<= div>
class Pixel {
  public readonly cl= ass Point(public int $x, public int $y) implements Vector2 use Evolvable= ;
}

// Create a new pixel poi= nt with property $x and $y set to 0
$p =3D new Pixel::Poin= t(0, 0);

There are far more details in the = RFC itself, so please check it out. I'm quite excited to hear your thoug= hts!

=E2=80=94 Ro= b

PS. I know= I tend to rush into things, but I want to make it clear that I'm not ru= shing this -- I've learned from my mistakes (thank you to those who have= given me advice). I'm going to do this right.

<= /div>


Hello internals,

I've made some major updates to the text of t= he RFC to clarify behaviors and revisited the implementation (which is s= till under development, though I hope to have a draft by the end of this= weekend). Here's a broad overview of what has changed in inner classes:=

- Accessing inner classes is done via a ne= w token: ":>" instead of "::".
- Inner classes may now = be infinitely nested.
- Inner classes may be declared `abs= tract`.
- Documented changes to ReflectionClass.
=
- Usage of `static` to refer to inner classes is restricted to prev= ent accidental violations of LSP.

Otherwise= , there are not any big changes, but a lot of time was spent clarifying = behavior and expanding on the reasoning for those decisions in the RFC i= tself.

=E2=80=94 Rob=

For those who are interested,= I've opened the PR that enables this feature: https://github.com/php/php-src/pull/18= 069

=E2=80=94 Rob
--1ae25b4bb160418d8d482a5b3b72b6e2--