> On 27 Jun 2024, at 13:11, Mike Schinkel <[email protected]> wrote:
>
>
>> On Jun 27, 2024, at 12:09 AM, Stephen Reay <[email protected] <mailto:[email protected]>> 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 class
>
>>> We 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 <[email protected] <mailto:[email protected]>> 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
>> <checks notes> 20 years next month.
>
> While it may be true that it has been that way, disallowing static methods
from
> being called using abstract static
classes would not be a BC break because it was
> previously impossible to declare a class as static
let alone abstract
> 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 a
> abstract 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 those static
methods from the
> abstract
class itself?
>
> More importantly, IF we do not immediately disallow calling static
methods on
> abstract 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 to abstract static
classes static
methods could be called on
> abstract
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