Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:123625 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 C0B361A009C for ; Sun, 16 Jun 2024 09:17:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1718529531; bh=qy1WIF9yQPdL7CJ61ItmryPdqqFIKOvgyhgKkD7cfOA=; h=Date:Subject:To:References:From:In-Reply-To:From; b=VJrKQn9td59pCE+TYHVn1H+BTsTlqRnadCGPI9rTGrSO6x9/ZkEC/sMTTnp/N3Z1u O5QSuW9am74npkJfd5EvG3Waa2BxK2j7WkfuIQTbh8ZEp54U0GYNbb9+JLRMCiGLnk vTf+7i/7OgaRAlfJGgOEf0CkGxsdQAAyNEWhl60HDHNzMuLX2+ejMJAGECNwr354UW 6KPE+rtXiXfPiETATwrygCiEpciap1H1blF9Mg8SWEBhLVVtnAylALRtD6xlEEb0zc 4vgbNvvNjgP27Cwzl+xifor2jeUIviVLwrSw6IGbyE0zc6yffXnCv/f8kR2fup7n55 ZC6ZmYYO9gy+A== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 86B1018065C for ; Sun, 16 Jun 2024 09:18:50 +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,DKIM_SIGNED, DKIM_VALID,DMARC_MISSING,HTML_MESSAGE,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,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 mail-wm1-f46.google.com (mail-wm1-f46.google.com [209.85.128.46]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Sun, 16 Jun 2024 09:18:50 +0000 (UTC) Received: by mail-wm1-f46.google.com with SMTP id 5b1f17b1804b1-4230366ad7bso29490045e9.1 for ; Sun, 16 Jun 2024 02:17:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=scriptfusion-com.20230601.gappssmtp.com; s=20230601; t=1718529457; x=1719134257; darn=lists.php.net; h=in-reply-to:from:content-language:references:to:subject:user-agent :mime-version:date:message-id:from:to:cc:subject:date:message-id :reply-to; bh=y/7z0noq197sU0QCR/2MU7YPJttybchfNxaqUWs3eV8=; b=HZ9HJlTkZk5iY2OMbrUcc7wX1iva+n/gd5fFroto6j9NUizccpn9qM5QMLRg3shxgg Q0XizWUwQhZVLQrPAbxbyS9CCc43oRXXVfD/bjHzkIguKyvZi8fKpmDVDHcle3N10o8Y 61YRMFkfSA8DPQspb/IPyaD/qR5BSu6eXPFA3Tyrq0LDDPQuyUdhIWCjcxq4snaXYgly izInxGzMx8tkj5ny8pqvPvya0TemjWWbVA6AtLH/ahAKfTdOngD07VKxEcnAjbBhpmR4 DUwzBT7IF+OgtdoAQpOXlqiYJeC86Y+5ZpremHzoMIWwP1HSttoOF7hxoNKtpY/APiEa q3ag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718529457; x=1719134257; h=in-reply-to:from:content-language:references:to:subject:user-agent :mime-version:date:message-id:x-gm-message-state:from:to:cc:subject :date:message-id:reply-to; bh=y/7z0noq197sU0QCR/2MU7YPJttybchfNxaqUWs3eV8=; b=lRjL8yWtkWwfXQvEhXCtYXqEDLH7OViwe6Rb7XPZtENA2a8OnVWDpw2kJlWRqeIxoG BJtHS+cxRnFWMhBJefawz3wFMayg6lG0HEuY+By9dI6qzXpV/rY0TkdzX0v7L+uO4Aet lCIxpQCAZr/GbU3XjhQNHnj3rzNkSJdtHoVmPgAqaGO0XsZTzzkIxkx8oStQ/Ik9rgZv ly92RlPrEM2kThsPMgVL11AjH1RB2cYRc96RW71/QkHiVWMh85ehy77EtUlJepdvcsAy ugJtKciV+SXik2mD9xp5qMgZbQ5FJ0Zysw+6zvgtf4DYRO90lASMtAH6M5NSjb9D8oTp U4vQ== X-Gm-Message-State: AOJu0YxQiT4gNCITepG+8FcRBtZlM6g6OdRGgan6IzmCqpMbjcPVtexe SLKV8tr11gOnSAODH2ttzYnhyA08DwHzd1daCQau5wxLhoNoC7h7vvL4a7IzAbDIJIwuU2vSBfe xaOk= X-Google-Smtp-Source: AGHT+IG0LNI02BajzXdyVuBALKzzvLDNmQt6mU/Bw3gB4TIh5nBxNkBYYG4BCRTavLBrvZTkGq3Q8Q== X-Received: by 2002:a05:600c:48a5:b0:421:7c1e:5d5d with SMTP id 5b1f17b1804b1-4230484c57fmr69195515e9.35.1718529457453; Sun, 16 Jun 2024 02:17:37 -0700 (PDT) Received: from ?IPV6:2a01:4b00:bf09:5101:5102:25f8:7874:c703? ([2a01:4b00:bf09:5101:5102:25f8:7874:c703]) by smtp.googlemail.com with ESMTPSA id 5b1f17b1804b1-422f602feb0sm120413305e9.20.2024.06.16.02.17.36 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 16 Jun 2024 02:17:37 -0700 (PDT) Content-Type: multipart/alternative; boundary="------------pjJq5oPjwJ7RvGzqwEh1wEBh" Message-ID: <04ae10a2-ceae-4996-a7fe-9b38d2f81ca2@scriptfusion.com> Date: Sun, 16 Jun 2024 10:17:37 +0100 Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PHP-DEV] Static class To: internals@lists.php.net References: <0cf69a14-f1b5-4077-9d91-d7b579485eec@scriptfusion.com> <936e1aa3-48cc-4552-9f68-676ebcdeb596@rwec.co.uk> Content-Language: en-GB In-Reply-To: <936e1aa3-48cc-4552-9f68-676ebcdeb596@rwec.co.uk> From: bilge@scriptfusion.com (Bilge) This is a multi-part message in MIME format. --------------pjJq5oPjwJ7RvGzqwEh1wEBh Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit 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, > --------------pjJq5oPjwJ7RvGzqwEh1wEBh Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit
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,


--------------pjJq5oPjwJ7RvGzqwEh1wEBh--