> On Jun 16, 2024, at 5:17 AM, Bilge <bi...@scriptfusion.com> wrote: > > Let's start getting specific so we can make some progress. > > The goals of this RFC are fairly straightforward: > Introduce the `static` keyword at the class level to preclude the need to > create a private constructor. That is, `__construct` would be invalid in a > static class. > Prohibit instantiation of a static class with a language-level error. > Prohibit declaration of instance members in a static class with a > language-level error. > However, as ever, there's a devil in the details. In particular, we need to > consider the following: >
To start, any limitations imposed on these new static classes that current classes can do that are not intrinsically linked to their "staticness" would result in developers grudgingly writing a class "statically" that is not declared as static. Imposing restrictions on features that developers use in the wild would certainly cause them to consider the feature to be dubiously excluded. Not supporting all features used in the wild would result in developers not being able to use static classes for new and/or refactored code if they believe they need those excluded features. This would stop developers from signaling their intent to readers of their code and would stop developers from being able to rely on reflection to discern static classes for new and/or refactored code when that otherwise could have been possible. Disabling existing features just for static classes would result in creating two forms of static classes — explicit and implicit — and that IMO would be a miss for the addition of static classes. That said... > 1. Since a "static class" implies all members are static, should we still > allow explicit static method declarations with the `static` keyword? > Yes, but optional. Supporting the static `keyword` for members would ease the transition for tooling, and support those who prefer to be explicit in all the things. OTOH, of all the things I mention below, this is my least firmly-held opinion. > 2. Should `static` imply `final`? > No. The primary PHP framework I wrote before I quite working professionally in PHP — although others still use it — has a series of implied static classes, all of which inherit from a base implied static class that provided services to all other implied static classes. To update this library to a newer version of PHP with static classes would not be possible if static classes are assumed to be `final`. Further, Laravel — which I have never used but is simultaneously the most beloved framework in PHP but also the most hated, depending on who you ask — has a base `Model` class that Eloquent models inherit from, and a `BaseController` for custom controllers. Enforcing `final` would leave Laravel out in the lurch for classes that are exactly the type of classes that should be declared static. If a developer wants their declared static class to be final they should be required to use the `final` keyword, IMO. BTW, see #4 and #5 why this is important. > 3. Should a "static class" prohibit inheritance? > Isn't #3 just a rewording of #2? > 4. Should a "static class" permit state? > Absolutely, without a doubt. My PHP library uses static properties to keep track of certain data which I treated as immutable — registering business information for use by static factory methods, and in some cases the factory methods use arrays to store instances they create for processing and/or dispensing on demand late by other static methods. Laravel uses static properties in their service containers such as `Illuminate\Support\Facades\App`, their Cache facade uses static properties, Eloquent models maintain state in static properties, and developer written factory classes often use static properties to track instances. While we can ignore my library it would be much harder to ignore Laravel's use of state in static properties. > 5. Should traits be permitted in a static class? > Of course. Laravel makes extensive use of traits in their implied static classes, in their core framework and in Eloquent models, and they encourage Laravel application developers to use traits in their applications. Traits are a valuable code structuring mechanism as an alternate to inheritance more like containment, and not supporting traits would, again, be leaving developers depending on it out in the cold. Also, final/inheritance might not be as critical to support if it were not for one capability that PHP's traits are glaringly missing and that is their inability to allow developers to declare properties and methods as private to the trait itself. Of course if we add trait-private to traits then it would be less problematic to implied `final`/not support inheritance, but I doubt we'd want to couple this potential RFC with one that hasn't even been considered yet. Even so, not supporting inheritance would mean not allowing implied static classes that use inheritance to be refactored to use the static declaration. > 6. Which magic methods (if any) should be valid in a static class? > Unless I am mistaken, the only magic method that support static function calls is `__callStatic()` as everything else deals with instances, so I assume that it is the only one that needs to be supported. And yes, IMO it is critical to support `__callStatic()` since Laravel Facades (as well as my own library) make use of it, and in Laravel's case, extensive use. Of course there may(?) be newer PHP features on the horizon that are an alternate to `__callStatic()` but supporting `__callStatic()` would make it easier for developers to move to static classes as even automated tooling could make the conversion if `__callStatic()` and all other features used in the wild are supported. Anyway, that is my take. #fwiw -Mike P.S. To learn about Laravel's uses of implied static classes I asked ChatGPT[1], so if I got anything wrong about Laravel I apologize as I was relying on ChatGPT not to hallucinate on this topic. I assumed it was unlikely to hallucinate given there was so much info on the web there is regarding Laravel for ChatGPT to train on. [1] https://chatgpt.com/share/79eb330b-69ae-4104-b2ac-6e77955ec914