> On 27 Jun 2024, at 13:11, Mike Schinkel <m...@newclarity.net> wrote:
> 
> 
>> On Jun 27, 2024, at 12:09 AM, Stephen Reay <php-li...@koalephant.com 
>> <mailto:php-li...@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 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 <php-li...@koalephant.com 
>> <mailto:php-li...@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 <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 

Reply via email to