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…
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.
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.
Isn’t #3 just a rewording of #2?
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.
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.
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
···
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:
-
Since a “static class” implies all members are static, should we still allow explicit static method declarations with the static
keyword?
-
Should static
imply final
?
-
Should a “static class” prohibit inheritance?
-
Should a “static class” permit state?
-
Should traits be permitted in a static class?
-
Which magic methods (if any) should be valid in a static class?