On 27 Jun 2024, at 13:11, Mike Schinkel mike@newclarity.net wrote:
On Jun 27, 2024, at 12:09 AM, Stephen Reay <php-lists@koalephant.com> wrote:
Hi Mike,
To answer your question: I believe
abstract static
should be allowed, because the “objection” mis-characterises a particular aspect of them as an unintended consequence, when there’s evidence to show that’s not that case.Claude essentially dismisses the use of abstract static methods:
only consequences of their intended meaning on non-static class
In v5.2 a strict standards notice was added regarding the use of abstract static methods in classes. No notice was ever shown when they’re used in interfaces. In v7 this notice was removed (via https://wiki.php.net/rfc/reclassify_e_strict#abstract_static_methods) because, as Nikita noted at the time:
Thank you for elaborating.
We are on the same page here as I too think
abstract static
should be allowed when declaring a classWe currently allow the use of abstract static functions in interfaces, as such it is inconsistent to not allow them as abstract methods. By using late static binding a method in the abstract class can reasonably depend on the existence of a static method in a superclass.
That to me says this is an intended feature, and not an unintended consequence.
Before I address this and your other comments, please understand that I do not see this as a huge issue either way, but I do want my argument to be understood. If my argument on this does not win the day, I will not lament it in any way.
As an aside, I had never seen interfaces used that way and found it surprising. Obviously I missed when Nikita made that claim.
As for “an intended feature, and not an unintended consequence,” when I was in university they drilled the idea of a sunken cost into me to the point I am a true believer. IOW, make the best decision moving forward vs. doubling down on bad decisions.
Note that I am not saying Nikita’s was a bad decision (or a good one) just that the existence of a prior decision should not color making the best decision moving forward.
I understand that, but I also think there is much value in consistency. If static methods (and abstract static methods) are supported, they should be supported consistently. There have been numerous RFCs passed that bring consistency (and thus remove developer surprise) to the language, even on features that some voters dislike so much, they’d rather the feature is intentionally difficult to use, to discourage use by other people (remember the trait constants RFC?)
I am curious, do you know of real-world userland code that is actually configured as your example that would be negatively affected by disallowing static methods calls?
Not in that specific case, no. I’ve seen some that uses abstract class
as a poor mans static class
(just to prevent instantiation) but not that uses abstract
to allow omitting an upstream method.
On Jun 26, 2024, at 4:26 AM, Stephen Reay <php-lists@koalephant.com> wrote:
This is an example of code that works today (and all the way back to 5.0): https://3v4l.org/4EKo2
The class hierarchy embody the type of classes this RFC is about: only static members, no instantiation.
The implemented methods can be called statically, regardless of whether the class they’re implemented in is abstract or not. The abstract methods cannot be called directly.
Understood, but I do not see how interfaces or instantiation or abstract method are relevant to the discussion. They all seem orthogonal to me.
A class cannot contain abstract methods if it is not also marked as abstract. That’s the whole point. If you prevent a static class from also being abstract, you prevent that class from partially implementing an interface (or parent class with abstract methods).
So these classes would be a candidate for the
static
class keyword (or Attribute) - except they can’t, if calls to implemented methods on abstract classes are disallowed. Because the Base::a() method has been publicly callable, for potentially as long as 20 years next month.While it may be true that it has been that way, disallowing
static methods
from being called usingabstract static
classes would not be a BC break because it was previously impossible to declare a class asstatic
let aloneabstract static
.
Right so I’m not actually saying this is a BC break itself - I’m saying the authors of the library/code then can’t adopt the static
keyword, which embodies their intent fully, because if they do so their code has a BC break (code that was previously callable, it not any more).
Further, there are often new features with constraints that result in developer not being “to do what they have been able to do for 20 years” because, looking forward, those constraints make more sense than not having those constraints.
Take a look at
readonly
properties. They must be typed, but I could have used the same argument against that saying “We’ve always been able to have untyped properties so readonly should not have to be typed.”[1] I’d say requiring them to be typed was a win, though, regardless of past property capabilities.
I don’t think the reason something has limitations should be ignored. It’s not like Nikita said “we should disallow untyped properties because otherwise we have to allow them forever”. It was specifically to prevent confusion due to the implicit null default on untyped properties. Also, this restriction was quite easy to work around, thanks to the mixed
type introduced in 8.0.
I’m not claiming necessarily that disallowing calling
static
methods on aabstract static
class is a best practice, but I am saying that “we’ve been able to do it with similar syntax for a long time” is not a particularly compelling argument if disallowing is a better approach.
As another aside, assuming everyone agrees on what a best practice is for a given case, I doubt anyone would object to a constraint that forced developers to follow that best practice vs. allowing them to write less ideal code.
My point here is that if someone wants to prohibit calling public static methods on abstract classes with the static keyword, that’s going be inconsistent with how it’s worked for the last 20 years (i.e. on classes that were ‘static’ in intent but not syntactically),
Back to sunken cost, does it make more sense to only give developers who want to disallow using static methods for their
abstract static
classes access to@internal docblock
— which I argued against elsewhere in this thread — and let Hyrum’s Law take over, OR do we enable them to disallow calling thosestatic
methods from theabstract
class itself?More importantly, IF we do not immediately disallow calling
static
methods onabstract static
classes then we will never be able to disallow in the future, because of BC. But on the flip side we could later open them up for calling if we found the limitation to be problematic.or if it applies the change everywhere it’s going to be a BC break.
And to be clear, I am against BC breaks in almost all cases. So bringing that up between us is moot.
All that said, if you tell me "I don’t care about closing the door on being able to disallow developers from calling static methods on
abstract static
methods because prior toabstract static
classesstatic
methods could be called onabstract
classes in the past" I will respect that, and as I said above, it won’t bother me.
Don’t care is the wrong term I think. As I’ve said, numerous times, I’m concerned about consistency first and foremost. If the voting powers that be deem calling a static method on an abstract class (regardless of the class’s other modifers/keywords) is too much of a pearl clutching moment, and it’s deprecated, I’ll probably ask pretty loudly “why, what actual problem does this prevent” but I’ll appreciate that it’s being consistent, despite the BC break.
My only reason for persisting is to ensure that the argument I was making was understood before it was dismissed.
I think I understand your view: you’re not as concerned with consistency if the alternative is something “better”.
-Mike
[1] Ignoring there were technical issues with allowing untyped to be readonly, which could have been gotten around somehow if the consensus was “They must be able to untyped.”
Cheers
Stephen