Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:126999 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 BE0CC1A00BC for ; Tue, 1 Apr 2025 10:09:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1743502052; bh=mCE3vAwzQ7jwEuHEOFri/DRzVeFkts0297VKDSFunsQ=; h=From:To:Subject:Date:From; b=EVbp5jZRf+98zo4TkPk6SHefUl0BKti5uJF6XdkQtPIs2NA1IqXtIjHbLQafqjUDB CjhNpLL4MDH+ZXtEY3MYGn6tR3sbgB5G090pLAvRB/G9UvodHe04xdSDb/YRT9PKuW yDFLKDSmcq0+kZ65tH9Tf2AKf7s6kJTZu5XNjbh/vKc10DQjnw+miuuItKPDi49+4v EHqwUQHM+z+oC1Qegw+ov7gwMXk+cM43hEOM/9mDxsj5i/CD8U+7W+M5crzNdaJCkG ict2oEwMxalU3KLylYCRvND+h68aQNgmox3Q6EIwFggm6uMyZSOTQVpPUT3kLMGLQD jQu9KH96WW/6g== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 0304B180053 for ; Tue, 1 Apr 2025 10:07:31 +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.6 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_50, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_MISSING, HTML_MESSAGE,RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE, SPF_PASS,T_PDS_PRO_TLD autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from siberian.tulip.relay.mailchannels.net (siberian.tulip.relay.mailchannels.net [23.83.218.246]) (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 ; Tue, 1 Apr 2025 10:07:30 +0000 (UTC) X-Sender-Id: yszpovajlk|x-authuser|juris@glaive.pro Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id 59E771A5AFB for ; Tue, 1 Apr 2025 10:09:56 +0000 (UTC) Received: from server42.areait.lv (100-96-205-116.trex-nlb.outbound.svc.cluster.local [100.96.205.116]) (Authenticated sender: yszpovajlk) by relay.mailchannels.net (Postfix) with ESMTPA id B92EC1A5B38 for ; Tue, 1 Apr 2025 10:09:55 +0000 (UTC) ARC-Seal: i=1; s=arc-2022; d=mailchannels.net; t=1743502196; a=rsa-sha256; cv=none; b=F5pFLM05fCQSxW+gT08NyGPZU/xgva7j0wGckUlyuLnrKs1FO7dBEYzlvy5WGWa0/AKgau ylc4d1qEaZf3L8MB22mFPajADk3F1IMUuQzpWs9avTwhADksdFCTMDZotdjoEaVzCPTS7I yYprYzT6yONb2M2mvW8qmJ7LokXngWbrEys7wXk58ZCjAGgUfrcH8dCKXn0H9mlc4I7s9X C5NfsJbu0JJJZpANkCLrVxWDnE/0JQLvjt7GKxKmLH5t+9m8tNLUWe+YRo8n9S9RlwDY/u CCR5FIhlIlRarZtYG9zJookrGZmbRy9Y21SocLrZkjDBD6vzBawbc+5Ho0Qy5Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=mailchannels.net; s=arc-2022; t=1743502196; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: dkim-signature; bh=5MLWwaoB0ICFQ1ImB1l/v8LvjGnVJAD0h+rILeap4u8=; b=d/Gs/RjFZBDzLqDeVs3N7QvULN/kBTKwVtzTXbFVQlXa1tkC8ttM8jUctGU9UuayQpjvq1 z272YPhdoVD4rUPa8dTxSalcpmAiRGeTpm499ec9N+ilw3eZ9bkftGELumP+Xl7lZcgmqm Bz/hStoEg3BYga4TVT2wfA/SNXZXMNApFlga5XAmVBnFrKci2Pd3nekjUjVWimImPtdGNf O+w7hV/bCjhGxG7oiyoOX9xIcez11BPMEAqn46UJ9wdLmUqdUqfq92bERlm2hJQCswTP+f j61r8xTkGkm8998SfaaEE1M8eyONSU21oDCcGgteHHgum38LLo1eb0/KbBD6fA== ARC-Authentication-Results: i=1; rspamd-85757496c5-x4xv5; auth=pass smtp.auth=yszpovajlk smtp.mailfrom=juris@glaive.pro X-Sender-Id: yszpovajlk|x-authuser|juris@glaive.pro X-MC-Relay: Neutral X-MailChannels-SenderId: yszpovajlk|x-authuser|juris@glaive.pro X-MailChannels-Auth-Id: yszpovajlk X-Tasty-Whimsical: 7b6148e07476dc5f_1743502196290_598625923 X-MC-Loop-Signature: 1743502196290:1188510194 X-MC-Ingress-Time: 1743502196290 Received: from server42.areait.lv (server42.areait.lv [212.7.207.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384) by 100.96.205.116 (trex/7.0.3); Tue, 01 Apr 2025 10:09:56 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=glaive.pro; s=default; h=Content-Type:MIME-Version:Message-ID:Date:Subject:To:From:Sender :Reply-To:Cc:Content-Transfer-Encoding:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=NB2QyhdTZu+zfY6nEmm7BndviugD0rcNIyqE3pkW8Qc=; b=Yw6ns5I1Cz+K6GdUilUbAf8FOZ 9qTIX5dGImntvWELgiDn1VLkK04AGoDslsyEeEDkpW2siCqCyLTtT1hUUkHIDZIIXFFxiCWsDSQ3R h/sM6W7fAqBU0mNOw41PO9gI6HAgdSoQBI5ZvASCDaAGSGeZN2+BJ2+M7mGYImojm0RHjctzUpknt txDkzbbakzUxMZVHuyAA/5wSXS1A3KuHdoqOHFRX0ns1Fbz5+GsxJTPn/P3XABTIFM3yNVDlazjXF jJ/6XVvp7a6LzyKPD4SJrnyCNpjDr3Uf0RMp/vuIPRRPGfZgPztyKtdYOCRaiSqMz14S5H0RkKTe3 yX1KEvfQ==; Received: from [77.93.29.116] (port=52742 helo=LAPTOPHKIOPCGI) by server42.areait.lv with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96.2) (envelope-from ) id 1tzYZ6-003PKs-2p for internals@lists.php.net; Tue, 01 Apr 2025 13:09:53 +0300 To: "'php internals'" Subject: [PHP-DEV] Usable classes? Date: Tue, 1 Apr 2025 13:09:52 +0300 Message-ID: <059201dba2ee$35c7bc00$a1573400$@glaive.pro> Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_0593_01DBA307.5B156930" X-Mailer: Microsoft Outlook 16.0 Thread-Index: AduiSkx6wc2VrQjeQyK/W4MAZPTwKQ== Content-Language: lv X-AuthUser: juris@glaive.pro From: juris@glaive.pro ("Juris Evertovskis") This is a multipart message in MIME format. ------=_NextPart_000_0593_01DBA307.5B156930 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Hello, Sorry, but I've got another idea. I already validated it with ChatGPT who labeled it spicy. After clarifying some misunderstandings, they updated the label to "heretical". I hope you'll find it exciting as well. As you're all aware, classes in PHP are literally unusable and impossible to implement. Id est class A {} class B implements A {} // this is not allowed in PHP class C { use A; // this is also not allowed in PHP } However, under the hood both interfaces and traits are classes, just with different vibes. I mean flags. The limitation feels almost artificial: https://github.com/php/php-src/blob/334d9bbc09e37d6f66dde23988df7d7299dc6f19 /Zend/zend_inheritance.c#L2248-L2252 https://github.com/php/php-src/blob/334d9bbc09e37d6f66dde23988df7d7299dc6f19 /Zend/zend_inheritance.c#L3554-L3558 I suspect it would be quite possible to drop these limitations, so the main question seems to be - are these limitations useful? Or would it be usefuler to have classes without such limits? Let me elaborate: ## Part A. Implementable classes. Idea: allow using normal classes in the interface list. class A {} class B implements A {} The result would be that B gets checked whether it satisfies the public interface of A. From there on B gets treated as a subclass of A: `(new B) instanceof A` is true and instances of B satisfy an A typehint. These days many projects, libraries and frameworks add a bunch of interfaces that each correspond to a single class (and mirror it's public signature) that might be replaced with a different implementation. Some libraries define a hundred interfaces while the consumer projects use at most a few of those replacement opportunities. These would make such just-in-case interface definitions redundant as the class itself could be used as the interface. In otter words: why make an interface if you've already defined the interface in that class right there? ## Part B. Usable classes Idea: allow using normal classes in the trait list. class A {} class B { use A; } The result would be that B gets the guts of A, just like if A was trait. This would simplify reuse and composition and reduce the need for workarounds (aka design patterns). Together they would simplify making libs that add features to your models or something like that. E.g. you can do this without splitting them into a trait and an interface and duplicating the signature. class YourModel implements SomeFeature { use SomeFeature; } ## Bonus feature You essentially get multiple inheritance free of charge as the conflict rules for both interfaces and traits are already well defined. class DoublyInherited implements A, B { use A, B; } As ChatGPT told me yesterday: Sure, this blurs the lines between classes, traits, and interfaces. But so does PHP in general. BR, Juris ------=_NextPart_000_0593_01DBA307.5B156930 Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable

Hello,

 

Sorry, but = I’ve got another idea. I already validated it with ChatGPT who = labeled it spicy. After clarifying some misunderstandings, they updated = the label to “heretical”. I hope you’ll find it = exciting as well.

 

As = you’re all aware, classes in PHP are literally unusable and = impossible to implement. Id est

 

    class A {}

    class B implements A {} // this is = not allowed in PHP

    = class C {

        use A; // = this is also not allowed in PHP

    }

 

However, = under the hood both interfaces and traits are classes, just with = different vibes. I mean flags. The limitation feels almost = artificial:

 

https://github.com/php/p= hp-src/blob/334d9bbc09e37d6f66dde23988df7d7299dc6f19/Zend/zend_inheritanc= e.c#L2248-L2252

https://github.com/php/p= hp-src/blob/334d9bbc09e37d6f66dde23988df7d7299dc6f19/Zend/zend_inheritanc= e.c#L3554-L3558

 

I suspect it = would be quite possible to drop these limitations, so the main question = seems to be — are these limitations useful? Or would it be = usefuler to have classes without such limits? Let me = elaborate:

 

## Part A. Implementable classes.

 

Idea: allow = using normal classes in the interface list.

 

    class A {}

    class B implements A = {}

 

The result would be that B gets checked whether it = satisfies the public interface of A. From there on B gets treated as a = subclass of A: `(new B) instanceof A` is true and instances of B satisfy = an A typehint.

 

These days = many projects, libraries and frameworks add a bunch of interfaces that = each correspond to a single class (and mirror it’s public = signature) that might be replaced with a different implementation. Some = libraries define a hundred interfaces while the consumer projects use at = most a few of those replacement opportunities.

 

These would = make such just-in-case interface definitions redundant as the class = itself could be used as the interface. In otter words: why make an = interface if you’ve already defined the interface in that class = right there?

 

## Part B. Usable classes

 

Idea: allow = using normal classes in the trait list.

 

    class A {}

    class B {

        use = A;

    = }

 

The result would be that B gets the guts of A, just = like if A was trait. This would simplify reuse and composition and = reduce the need for workarounds (aka design patterns).

 

Together = they would simplify making libs that add features to your models or = something like that. E.g. you can do this without splitting them into a = trait and an interface and duplicating the signature.

 

    class YourModel implements = SomeFeature {

        use = SomeFeature;

    = }

 

## Bonus feature

 

You = essentially get multiple inheritance free of charge as the conflict = rules for both interfaces and traits are already well = defined.

 

    class DoublyInherited implements A, = B {

        use A, = B;

    = }

 

As ChatGPT told me yesterday: Sure, this blurs the = lines between classes, traits, and interfaces. But so does PHP in = general.

 

BR,

Juris

------=_NextPart_000_0593_01DBA307.5B156930--