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:

  1. Since a "static class" implies all members are static, should we still allow explicit static method declarations with the `static` keyword?
  2. Should `static` imply `final`?
    2a. If yes, should `final` still be allowed to be explicitly declared, despite being implied?
  3. Should a "static class" prohibit inheritance?
  4. Should a "static class" permit state?
  5. Should traits be permitted in a static class?
  6. Which magic methods (if any) should be valid in a static class?

Based on my current understanding, I would propose the following answers to these questions:

  1. In order to make upgrading simple and keep method intentions clear, `static` should not only be valid but also required on each method declaration, as usual for static methods.   2. Inheritance doesn't make much sense in a purely static context, despite the fact that PHP has a static resolution operator; I often find this is an anti-pattern. In any case, this is a non-BC issue if we lock down inheritance for now and later decide to open it up. Disabling inheritance also is in-line with the C# implementation of the same.     2a. Since under this proposal, `final` is implied, it should not be necessary (or allowed) to be specified. Upgrading would be simply a case of replacing `final` with `static` in-place.   3. As already mentioned, inheritance in a purely static context doesn't make much sense, and it's a non-BC break to prohibit it and later enable it. This decision is also in-line with the C# implementation.   4. Perhaps the most contentious decision, we could disable state and later enable it if there is a need, without BC. I personally cannot think of a time when I needed state in a static class. That said, I do not agree with disabling state within the language. In case someone is relying on static state in such a class, upgrading would be impossible; they would instead have to avoid marking the class as static, which defeats the purpose of this RFC. I believe we should support state, and if someone dislikes static state, they should enforce that with a code style rule in their project; this is not something that should be prohibited by the language itself as "regular" classes already allow this.   5. Provided a trait follows the rules of the static class (i.e. all members are static), it seems to me this should be allowed, though I have little use for it myself.   6. Given there are many magic methods, this topic probably deserves a separate discussion; it is not something I have spent a lot of time on thus far so it is just included for visibility at this time.

If there are any strongly dissenting opinions on any of these points, or any significant points I may have missed, please share. Otherwise, I would be happy to draw up and RFC along these lines (notwithstanding I have no RFC karma at present), followed by an implementation once all outstanding questions are answered.

Cheers,
Bilge


On 15/06/2024 14:53, Rowan Tommins [IMSoP] wrote:
On 15/06/2024 12:16, Bilge wrote:

I want to introduce the `static` keyword at the class declaration level. That is, the following would be valid: `static class Foo {}`.


This has been proposed before, and was rejected at vote. It was nearly 10 years ago, so opinions may have changed, but it would be worth reading through the prior discussion to anticipate or counter the objections raised, and avoid re-treading the same ground.

- RFC: https://wiki.php.net/rfc/abstract_final_class
- Pre-vote discussion threads: https://externals.io/message/79211 and https://externals.io/message/79338
- Final vote thread: https://externals.io/message/79601

Searching my list archive, I find that it came up again a few months ago, which I'd entirely forgotten: https://externals.io/message/121717

Slightly tangential, but some of the same discussion also came up on these rather lengthy threads about "static class constructors": https://externals.io/message/84602 and https://externals.io/message/85779


Regards,

Reply via email to