Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:123863 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id 67F021AD8EA for ; Wed, 26 Jun 2024 08:27:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1719390505; bh=sMivEU/lqjy8ZAOb8kKU0cxi13oz8SAQ3xsfKJlopC0=; h=From:Subject:Date:In-Reply-To:Cc:To:References:From; b=mM3UjjLNHTXdFyrFjgOAN9ISI5UyavBSyDxy2Z79i4Hu0feO6pRo0y8jlh5XoSbDK 8Eovyy2MbedqJO+gQOSbVixkVA7tjNQL1tvy+nh5dAoidUYx2IStKR3l5+3JrN432o s+n0q9iAutwmU2uuFvRR0Run7HHQOwmL4y8kNh8jD+6+e8gTPyna2GxDsI1XgalW0u JJ592Ljkm315dJ4LDa/45VOZCf+80mWGzFVra9pVrRKXDqIJedlpQW4orxFqG1vKaj JPkcYl6Ii5+0mU14AORq9ZgIGzM6+bLBf66dTPkqkRORo0l3KeJ4k20M6II21jyjTr HRUQACy4SKv1g== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id A19EB180A9E for ; Wed, 26 Jun 2024 08:28:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50,DMARC_MISSING, HTML_MESSAGE,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: Error (Cannot connect to unix socket '/var/run/clamav/clamd.ctl': connect: Connection refused) X-Envelope-From: Received: from mail1.25mail.st (mail1.25mail.st [206.123.115.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 26 Jun 2024 08:28:19 +0000 (UTC) Received: from smtpclient.apple (unknown [49.48.245.122]) by mail1.25mail.st (Postfix) with ESMTPSA id 5C38160379; Wed, 26 Jun 2024 08:26:48 +0000 (UTC) Message-ID: Content-Type: multipart/alternative; boundary="Apple-Mail=_21713968-0F31-41B2-AD35-3DEEE2121331" Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3774.600.62\)) Subject: Re: [PHP-DEV] [RFC] Static class Date: Wed, 26 Jun 2024 15:26:35 +0700 In-Reply-To: Cc: Claude Pache , ayesh@php.watch, Bilge , php internals To: Mike Schinkel References: <88D83E92-94BE-4548-B398-8F5C74765FFD@gmail.com> <882BD9E0-42E9-4C84-A144-7C1DFC4CE5EB@newclarity.net> X-Mailer: Apple Mail (2.3774.600.62) From: php-lists@koalephant.com (Stephen Reay) --Apple-Mail=_21713968-0F31-41B2-AD35-3DEEE2121331 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii > On 26 Jun 2024, at 12:51, Mike Schinkel wrote: >=20 >> On Jun 24, 2024, at 11:17 PM, Stephen Reay > wrote: >>=20 >>=20 >>=20 >>> On 25 Jun 2024, at 09:22, Mike Schinkel > wrote: >>>=20 >>>> On Jun 24, 2024, at 3:53 AM, Ayesh Karunaratne > wrote: >>>> - Why is it a class-level flag and not an attribute (similar to the >>>> `#[Override]` attribute in PHP 8.3) ? >>>=20 >>> =46rom my perspective that would create much confusion among every = PHP developer who has not committed to memory when to use `static` as a = class keyword and when to use it as an attribute. >>>=20 >>> Given the concept already exists in keywords I would strongly argue = that it makes no sense to introduce as an attributes in core PHP. =20 >>>=20 >>> Attributes are great for concepts new to PHP, IMO, but not for = existing concepts already part of PHP implemented with keywords. >>>=20 >>>> On Jun 24, 2024, at 4:27 AM, Claude Pache > wrote: >>>> * The main purpose of the `abstract` keyword is to prevent a class = to be instantiated, which (in case of static class) is more semantically = described by the `static` marker. Beyond that, it just allows to declare = a method that, if implemented by a subclass, should have a compatible = signature. Most notably, it does not prevent the other static members of = the class to be used directly. >>>=20 >>> Given a primary purpose for being able to declare a class `static` = is to signal intent, disallowing `abstract static` classes seems at odds = with that goal. >>>=20 >>> Of course it is currently true that `static` methods of `abstract` = classes can be called from outside a class and its class hierarchy, so = if we allow declaring `abstract static` classes then it would never in = the future be possible to lock down calls of `static` methods to those = `abstract` classes. >>>=20 >>> So IMO it would be better to disallow calling `static` methods from = outside a declared `abstract static` class and its inheritance hierarchy = as part of this RFC. That would be backward compatible since there are = currently no classes that are declared in that manner. Doing otherwise = would force those who want to declare a class as both `static` and = `abstract` to have to make a choice rather than being able to signal = their full intent. Which brings us back to the "implied" vs. "explicitly = declared" bifurcation I mentioned in a prior email. >>>=20 >>> BTW, I am assuming it is technically possible to disallow calling = methods for classes declared both `abstract` and `static` without = considerable difficulty in implementation and without creating a = significant drain on performance.=20 >>>=20 >>> -Mike=20 >>>=20 >>> P.S. I would argue the same for `readonly static` properties, but as = that seems those would require an involved discussion about the exact = rules to implement I am demurring on that topic. >>=20 >> Hi Mike, >>=20 >>=20 >>> So IMO it would be better to disallow calling `static` methods from = outside a declared `abstract static` class >>=20 >> Can you explain what you mean by this, or more specifically the = "why". What (implied wrong/bad) scenario are you trying to prevent, by = disallowing a static method on an abstract class to be called? >>=20 >> As you point out, it's already possible to call (public) static = methods on abstract classes, the same as it's possible to call (public) = static methods without instantiating a regular class. >>=20 >> So why should static abstract classes be different? If the static = method shouldn't be called publicly, it shouldn't be public. Are you = suggesting that public static methods shouldn't be callable on *any* = abstract class? If so, this sounds like a huge BC break, and if not, it = sounds like a confusing "if-then-but-why" scenario. >=20 > Thank you for the question. >=20 > I was not specifically advocating `static` methods to be disallowed to = be called on an `abstract` class. I was instead addressing the desire by = another list member to have classes declared `static` not also be able = to be declared `abstract.` That person made the argument that if = 'abstract static` did not actually have any effect then it should not be = allowed by the RFC.=20 >=20 > What affect are we talking about? If it is both `abstract` and = `static` then it would seem to me the only effect such a declaration = could have would be to disallow the calling of static methods using the = named abstract static class, e.g.: >=20 > abstract static class Base { > static public foo() { > echo "foo() called\n" > } > } > static class Concrete extends Base {} >=20 > Concrete::foo(); // works > Base::foo(); // fails >=20 > My only real argument for disallowing static method calls on abstract = static classes is that if we didn't do so initially we would never be = able to disallow because of BC. >=20 > In summary, my argument was really only about ensuring we allow = "abstract static" declaration so developers can signal intent and also = to address the objections of the other list member. But if given the = option, I think it would be good to disallow calling static methods on = abstract static classes if only to reserve the right to allow in the = future vs. closing that door immediately. Still, that latter is not the = hill for me to die on. >=20 >> I agree that the `static` keyword is a much better fit here, however = there is one other aspect here that may come into it (as much as I = prefer the keyword approach): the Attribute approach is backwards = compatible (with a polyfill) to let code using this feature also run on = previous PHP releases. Given that this is mostly intended as a way to = signal intent about a pattern that's already in use, this may be = significant for library authors. >=20 > Well, as previously stated, I think that would be confusing.=20 >=20 > Though I do see your reasoning for wanting it to be an attribute. = However... >=20 >> Personally (as a library author) I don't think that ability is worth = the weirdness of an attribute vs a keyword, but it may be more important = for others who are voting, and I'd rather have the feature with slightly = odd syntax rather than not at all. >=20 > I too am not convinced that the ongoing confusion would be better than = the temporary need to support older versions of PHP with the same source = file.=20 >=20 > Given that a build step could address the syntax there are certainly = other new language features that require developers to bifurcate their = libraries to support different versions, why make this one unique? >=20 > That said, it could be a voting option for the RFC? >=20 >=20 > -Mike Hi Mike, 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.=20 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. 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. 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), or if it applies = the change everywhere it's going to be a BC break. Re: attribute vs keyword, Like I said - I'm not personally in favour of the attribute approach; = I'm simply making the point (playing devils advocate if you will) that = by the very nature of how attributes work, they're more friendly to = supporting older versions of the language with a single code base. If = the general consensus is that it isn't a concern, great. But this = wouldn't be the first time we've seen a relatively minor syntax choice = derail an otherwise useful RFC. Cheers Stephen=20= --Apple-Mail=_21713968-0F31-41B2-AD35-3DEEE2121331 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=us-ascii

On 26 Jun 2024, at 12:51, Mike Schinkel = <mike@newclarity.net> wrote:

On Jun 24, 2024, at 11:17 PM, Stephen Reay = <php-lists@koalephant.com> = wrote:



On 25 Jun 2024, at 09:22, Mike Schinkel <mike@newclarity.net> = wrote:

On Jun = 24, 2024, at 3:53 AM, Ayesh Karunaratne <ayesh@php.watch> = wrote:
- Why is it a class-level flag and not an attribute = (similar to the
`#[Override]` attribute in PHP 8.3) = ?

=46rom my perspective that = would create much confusion among every PHP developer who has not = committed to memory when to use `static` as a class keyword and when to = use it as an attribute.

Given the concept = already exists in keywords I would strongly argue that it makes no sense = to introduce as an attributes in core PHP. =  

Attributes are great for concepts new to = PHP, IMO, but not for existing concepts already part of PHP implemented = with keywords.

On Jun 24, 2024, at 4:27 AM, Claude Pache <claude.pache@gmail.com> = wrote:
* The main purpose of the `abstract` keyword is to = prevent a class to be instantiated, which (in case of static class) is = more semantically described by the `static` marker. Beyond that, it just = allows to declare a method that, if implemented by a subclass, should = have a compatible signature. Most notably, it does not prevent the other = static members of the class to be used = directly.

Given a primary purpose for being able to declare a = class `static` is to signal intent, = disallowing `abstract static` classes seems at odds with that = goal.

Of course it is currently true that = `static` methods of `abstract` classes can be called from outside a =  class and its class hierarchy, so if we allow declaring `abstract = static` classes then it would never in the future be possible to lock = down calls of `static` methods to those `abstract` = classes.

So IMO it would be better = to disallow calling `static` methods from outside a declared `abstract = static` class and its inheritance hierarchy as part of this RFC. That = would be backward compatible since there are currently no classes that = are declared in that manner.  Doing otherwise would force those who = want to declare a class as both `static` and `abstract` to have to make = a choice rather than being able to signal their full intent. Which = brings us back to the "implied" vs. "explicitly = declared" bifurcation I mentioned in = a prior email.

BTW, I am assuming it is = technically possible to disallow calling methods for classes declared = both `abstract` and `static` without considerable difficulty in = implementation and without creating a significant drain on = performance. 

-Mike 
=
P.S. I would argue the same for `readonly static` properties, = but as that seems those would require an involved discussion about the = exact rules to implement I am demurring on that = topic.

Hi = Mike,


So IMO it would be better to = disallow calling `static` methods from outside a declared `abstract = static` class

Can you explain = what you mean by this, or more specifically the "why". What (implied = wrong/bad) scenario are you trying to prevent, by disallowing a static = method on an abstract class to be = called?

As you point out, it's already = possible to call (public) static methods on abstract classes, the same = as it's possible to call (public) static methods without instantiating a = regular class.

 So why should static = abstract classes be different? If the static method shouldn't be called = publicly, it shouldn't be public. Are you suggesting that public static = methods shouldn't be callable on *any* abstract class? If so, this = sounds like a huge BC break, and if not, it sounds like a confusing = "if-then-but-why" scenario.

Thank = you for the question.

I was not specifically advocating `static` = methods to be disallowed to be called on an `abstract` class. I was = instead addressing the desire by another list member to have classes = declared `static` not also be able to be declared `abstract.` That = person made the argument that if 'abstract static` did not actually have = any effect then it should not be allowed by the RFC. 


What affect are we talking about?  If it is both `abstract` = and `static` then it would seem to me the only effect such a declaration = could have would be to disallow the calling of static methods using the = named abstract static class, e.g.:

abstract static class Base {
  =  static public foo() {
      echo "foo() = called\n"
   }
}
static class Concrete extends Base = {}

Concrete::foo();  // = works
Base::foo();        // = fails

My only real argument for disallowing = static method calls on abstract static classes is that if we didn't do = so initially we would never be able to disallow because of = BC.

In summary, my argument was really only about ensuring we allow = "abstract static" declaration so developers can signal intent and also = to address the objections of the other list member. But if given the = option, I think it would be good to disallow calling static methods on = abstract static classes if only to reserve the right to allow in the = future vs. closing that door immediately. Still, that latter is not the = hill for me to die on.

I agree that the `static` keyword = is a much better fit here, however there is one other aspect here that = may come into it (as much as I prefer the keyword approach): the = Attribute approach is backwards compatible (with a polyfill) to let code = using this feature also run on previous PHP releases. Given that this is = mostly intended as a way to signal intent about a pattern that's already = in use, this may be significant for library = authors.

Well, as previously = stated, I think that would be confusing. 

Though I do see = your reasoning for wanting it to be an attribute. However...

Personally (as a library author) I don't think = that ability is worth the weirdness of an attribute vs a keyword, but it = may be more important for others who are voting, and I'd rather have the = feature with slightly odd syntax rather than not at = all.

I too am not convinced = that the ongoing confusion would be better than the temporary need to = support older versions of PHP with the same source = file. 

Given that a build step could = address the syntax there are certainly other new language features that = require developers to bifurcate their libraries to support different = versions, why make this one unique?

That said, = it could be a voting option for the RFC?

-Mike
<= /blockquote>

Hi Mike,

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.


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.

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), or if it applies the change everywhere = it's going to be a BC break.


Re: attribute vs keyword,

Like I said - = I'm not personally in favour of the attribute approach; I'm simply = making the point (playing devils advocate if you will) that by the very = nature of how attributes work, they're more friendly to supporting older = versions of the language with a single code base. If the general = consensus is that it isn't a concern, great. But this wouldn't be the = first time we've seen a relatively minor syntax choice derail an = otherwise useful RFC.


Cheers

Stephen 
= --Apple-Mail=_21713968-0F31-41B2-AD35-3DEEE2121331--