Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:119584 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 33193 invoked from network); 21 Feb 2023 11:52:48 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 21 Feb 2023 11:52:48 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id A0390180506 for ; Tue, 21 Feb 2023 03:52:47 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-0.7 required=5.0 tests=BAYES_05,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-vs1-f51.google.com (mail-vs1-f51.google.com [209.85.217.51]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Tue, 21 Feb 2023 03:52:47 -0800 (PST) Received: by mail-vs1-f51.google.com with SMTP id f31so4040213vsv.1 for ; Tue, 21 Feb 2023 03:52:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; t=1676980366; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=dA0Aq5oEVPizKE1wEbyBQinULPqEokLrAKdhtlOa9MI=; b=ihhHvxN2N1Y1O5COB8kgm6dEGctPmZCe1FFejImgXA38Llbvl7aw+MypwRX1q/qs4v VjBVyehZOtpSU5i/Ry116Ha89XpjffJiyDHjIAqUmRljK/C+kKfbYIOAKjQfv9eLc6ja CZ/8tQfXR5p81MU5czz9HypB5VQVbWZxzlC6EdYwGnuiPcoQWgbMG10cjyqh/3zzPbWG 1OXqnbHErs9XGu7j1mVGOD1TpjeoBrnzKQd/wgSHm+FC7dNQb5RO/XPPiIZN8LkRfu9f B1Z4I1Hz/SIzv5JlU4o44MxW0etSUb7YcOxlxx20isATml1H6BUTzZpC++RWxqZvGM2m 5hfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1676980366; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=dA0Aq5oEVPizKE1wEbyBQinULPqEokLrAKdhtlOa9MI=; b=A6oK5n10b93P86CIXbu+u50MeijNmMo0WN6PeqhNHL6nsoHD8g0UGW6q+jdy4Pz/Qw vaC4x1mEU6P72HvhgRqmwp0PMBWuz9v9REjN9D4/WADnW1PPYL0339Kxxi6mDuCpQhCs 5kkB0yepr4WaiamMEQBOhFsDhu5euMUa08ZD+Yfcm9GM6pyrQHnFe8AEOhkMrMDHYgCj MESyzvP0PdyH79EpsQroo9x9zkowaypRGZ2rGRoGa3xPQKOYjyXGj/n3ejZ0tgwRKxBr o2JPe//rH7peI1sKHAFXc726TOITUVlxsxQo4o1n06zq5fVCqUD+kP7D1qR/7JdtoOEM emgQ== X-Gm-Message-State: AO0yUKWx5zEFhGyVCAuhczDQmzOvUpnmZDBa5Q/EjEzUGZ8KTv5XTTkz QxGdG2PBwEn5J2bq02kaZGxOgpEyW/w0nr9wPNh1+mUdDl9DPPmb X-Google-Smtp-Source: AK7set8oKUgyZlMEnq8SwrxAIdWOfOulyCVs9KNJE05RnEalkly5s7yPMWshjw47Tn4qj3QhzDODCqFqI2lD0UMAYnY= X-Received: by 2002:a05:6102:2367:b0:41e:9598:e126 with SMTP id o7-20020a056102236700b0041e9598e126mr270992vsa.66.1676980366299; Tue, 21 Feb 2023 03:52:46 -0800 (PST) MIME-Version: 1.0 Date: Tue, 21 Feb 2023 13:52:35 +0200 Message-ID: To: php internals Content-Type: text/plain; charset="UTF-8" Subject: Class Re-implementation Mechanism From: someniatko@gmail.com (someniatko) Hi again, internals My marathon of some crazy ideas continues :D, with less crazy one this time. ## Idea Allow "reimplementing" the non-static public API (that is public properties and methods, excluding constructor) of a class by other classes like this: ```php final class interface A { public string $s; public function __construct(string $s) { $this->s = $s; } public static function fromInt(int $i): self { return new self((string) $i); } public function foo(): int { return 42; } } final class B implements A { public string $s = 'hello'; public function foo(): int { return 69; } } function usesA(A $param): void {} usesA(new B); // this works ``` ## Explanation Consider there is a class like this: ```php final class Service { public function __construct(private SomeDependency $dependency) {} // ... } final class SomeDependency { // ... } ``` We want to write some tests for the Service class, but we don't want to use a real SomeDependency instance during tests. A common approach is to either extract an interface (JUST to make it testable), or to drop the `final` keyword and allow extending the class. Both approaches have their flaws: - extracting an interface unnecessarily complicates the system, where only one "real" implementation of an interface is assumed. - dropping the `final` keyword allows for the rabbit-hole of inheritance abuse, like greatly described in this article: https://front-line-php.com/object-oriented I believe I came up with a better idea: what if we could leave both benefits of prohibiting the inheritance abuse and also allow not to clutter our namespace with excess entities like interfaces? I hereby suggest to combine the responsibilities of a class and an interface into one thing like that: ```php final class interface C {} final class D implements C {} ``` Now other classes can "implement" this class as well. Introduction of the new syntax (`class interface`) also solves BC problem - if you want to forbid your classes to be reimplemented whatsoever, you can still stick to the `final class` syntax. Although it is also possible to allow "reimplementing" ANY class, then new syntax is not needed - but some library writers like Marco Pivetta could be sad about that I suppose. Soo..., what do you think? Could this be a valuable addition to the language? Regards, Illia / someniatko