Re: Re: RFC: short and inner classes
| From: | Rob Landers | Date: | Fri, 14 Mar 2025 18:46:22 +0000 |
| Subject: | Re: Re: RFC: short and inner classes | ||
| References: | 1 2 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-126761@lists.php.net to get a copy of this message | ||
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,
>>
>> I'd like to introduce my RFC for discussion:
>> https://wiki.php.net/rfc/short-and-inner-classes
>>
>> 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 related to different/new/incorrect error
>> messages being generated. However, the core functionality exists to take for a test ride.
>>
>> So, what do I mean by "unprecedented amount of control"? With this change, you
>> can declare an inner class as private or protected, preventing its usage outside of the outer class:
>>
>> class User {
>> private class Id {}
>>
>> public function __construct(public self::Id $id) {}
>> }
>>
>> In the above example, the class
User is impossible to
>> construct even though it has a public constructor (except through reflection) because User::Id is
>> private; User::Id cannot be instantiated, used as a type hint, or even via
>> instanceof outside of the User class itself. This example 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.
>>
>> As a number of inner classes will probably be used as DTOs, the RFC introduces a
>> "short syntax" for declaring classes, which enhances expressiveness, even allowing the
>> usage of traits, all in a single line:
>>
>> // declare a readonly Point, that implements Vector2 and uses the Evolvable trait
>> readonly class Point(public int $x, public int $y) implements Vector2 use Evolvable;
>>
>> When combined with inner classes, it looks something like this:
>>
>> class Pixel {
>> public readonly class Point(public int $x, public int $y) implements Vector2 use
>> Evolvable;
>> }
>>
>> // Create a new pixel point with property $x and $y set to 0
>> $p = new Pixel::Point(0, 0);
>>
>> There are far more details in the RFC itself, so please check it out. I'm quite
>> excited to hear your thoughts!
>>
>> — Rob
>>
>> PS. I know I tend to rush into things, but I want to make it clear that I'm not
>> rushing this -- I've learned from my mistakes (thank you to those who have given me advice).
>> I'm going to do this right.
>>
>>
>
> Hello internals,
>
> I've made some major updates to the text of the RFC to clarify behaviors and revisited the
> implementation (which is still 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 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.
>
> 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 itself.
>
> — Rob
For those who are interested, I've opened the PR that enables this feature: https://github.com/php/php-src/pull/18069
— Rob