Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:110465 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 68324 invoked from network); 10 Jun 2020 17:43:16 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 10 Jun 2020 17:43:16 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 2DB9B180544 for ; Wed, 10 Jun 2020 09:27:14 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_LOW,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS11403 64.147.123.0/24 X-Spam-Virus: No X-Envelope-From: Received: from wout3-smtp.messagingengine.com (wout3-smtp.messagingengine.com [64.147.123.19]) (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, 10 Jun 2020 09:27:13 -0700 (PDT) Received: from compute7.internal (compute7.nyi.internal [10.202.2.47]) by mailout.west.internal (Postfix) with ESMTP id 7044E5FE for ; Wed, 10 Jun 2020 12:27:12 -0400 (EDT) Received: from imap26 ([10.202.2.76]) by compute7.internal (MEProxy); Wed, 10 Jun 2020 12:27:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm3; bh=v1GN9T+MtjOZCTw3if6yjqwj+dAUeFo5b3223piAD OQ=; b=V7l0q2UcySqHvjHv+BqklzkUq3FjwHdMAYn1C5vH/M7l91PDZ2aqrttnm zTkzKalsjlIwAp/s/thhAEr4Ng9i20hWjV55acdMdUbEdUO/YunumHjP6bjwKxLe gTMQz9IprYydTJvxa5R1IblbKK62eHYu8TYV/BjA8J0IYRydWjeLTMalTMeyYDje vnaTvgIYxBQsHbDXyRoX7eJdfTtOI9LyCTsJsNY5Dv3LIEBT9TmnPcMS981rEMBw DqjyNh0BhGAQs4xc5z/GTfoj6IVIAeZZNcWq0YczuHbCjTMX9hDe+NWJ1b+EmfqD e8n8WoKxaw7YqIdmz/j7XYdKvBsOw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeduhedrudehiedguddtfecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpefofgggkfgjfhffhffvufgtgfesthhqredtreerjeenucfhrhhomhepfdfn rghrrhihucfirghrfhhivghlugdfuceolhgrrhhrhiesghgrrhhfihgvlhguthgvtghhrd gtohhmqeenucggtffrrghtthgvrhhnpeehvdegffdvkeehleejtdekteegveetuefggefg lefhkeejgfefkeejieeiheefteenucffohhmrghinhepghgrrhhfihgvlhguthgvtghhrd gtohhmnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhep lhgrrhhrhiesghgrrhhfihgvlhguthgvtghhrdgtohhm X-ME-Proxy: Received: by mailuser.nyi.internal (Postfix, from userid 501) id 856EC14200A2; Wed, 10 Jun 2020 12:27:11 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.3.0-dev0-525-ge8fa799-fm-20200609.001-ge8fa7990 Mime-Version: 1.0 Message-ID: <587f662b-89a0-4f7b-a66c-261464cea708@www.fastmail.com> In-Reply-To: References: Date: Wed, 10 Jun 2020 11:26:51 -0500 To: "php internals" Content-Type: text/plain;charset=utf-8 Content-Transfer-Encoding: quoted-printable Subject: Re: [PHP-DEV] RFC: separate inheritance from subtyping (PHP v8) From: larry@garfieldtech.com ("Larry Garfield") On Wed, Jun 10, 2020, at 11:16 AM, Doug Wilbourne wrote: > I propose the following language additions: >=20 >=20 >=20 > 1) add three new keywords to the available syntax for class declaratio= ns: > 'inherits' and 'subtypes' and 'patterns'. >=20 >=20 >=20 > Currently the 'extends' keyword means both inherits and subtypes, > which leads to unnecessarily restrictive typing problems in order to > satisfy the Liskov substitution principle. 'Inherits' would mean that= > class A inherits B's properties and methods but is not a subtype of B = and > cannot be substituted for B. And just as A can override/overload B's > methods, the method signatures would not be subject to the parameter > widening / return-type restricting principle necessary for substitutio= n. > Conversely, the 'subtypes' keyword indicates that if A subtypes B then= A > can be substituted anywhere B can be used but 'subtypes' does not impl= y > that A inherits any of B's methods and properties - simply that it has= > signatures that conform to the parameter widening and return-type > restricting principles of substitution. Lastly 'patterns' complements= the > 'implements' keyword. A class 'patterns' an interface if it conforms = to > the declared signature of the interface but it does not imply that the= > concrete class can be substituted for any other object which either > implements or patterns the interface. >=20 >=20 >=20 > It should be possible to write 'A inherits, subtypes B' and this shoul= d > have the same effect as 'A extends B'. >=20 >=20 >=20 > 2) Add two new operators: 'descendentof' and 'subtypeof' that would au= gment > 'instanceof'. Semantics parallel the class declaration keywords descr= ibed > above. >=20 >=20 >=20 >=20 >=20 > Benefits: >=20 >=20 >=20 > It would then be possible to write something like the following: >=20 >=20 >=20 > interface ValidatorInterface >=20 > { >=20 > public function validate($x) : bool; >=20 > public function getErrmsg() : string; >=20 > } >=20 >=20 >=20 > abstract class Validator patterns ValidatorInterface >=20 > { >=20 > abstract public function validate($x) : bool; >=20 >=20 >=20 > public function getErrmsg() : string >=20 > { >=20 > return $this->errmsg; >=20 > } >=20 > } >=20 >=20 >=20 > class ValidatorNonNegativeInteger inherits Validator patterns > ValidatorInterface >=20 > { >=20 > public function validate(int $x) : bool { return 0 <=3D $x; } >=20 > } >=20 >=20 >=20 > class ValidatorAlphaText(string $x) inherits Validator patterns > ValidatorInterface : bool >=20 > { >=20 > return 1 =3D=3D preg_match('/^[a-zA-Z]+$/', $x); >=20 > } >=20 >=20 >=20 > ValidatorNonNegativeInteger and ValidatorAlphaText cannot be substitut= ed > for each other or Validator or ValidatorInterface. Explicitly trying = to > upcast ValidatorNonNegativeInteger should produce a compiler error (e.= g. > (Validator) new ValidatorNonNegativeInteger() is not legal). >=20 >=20 >=20 > If you adopt the data type 'mixed' and use it as in "public function > validate(mixed $x)", it makes it even clearer that the syntax permits > covariant parameters. >=20 >=20 >=20 > Currently the compiler allows contradictory parameter declaration betw= een > parent and descendant (using 'extends') but produces a runtime error > indicating that the child method's parameter must conform to that of t= he > parent. Because substitution is not an issue when A inherits B (using= > =E2=80=98inherits=E2=80=99 as above, not =E2=80=98extends=E2=80=99), a= parent declaring "function foo(int > $bar)" and a descendant declaring "function foo(string $bar)" has no > theoretical problem as far as I can tell and should not produce an err= or. >=20 >=20 >=20 > Along with generics (already being suggested / discussed I think - and= > thank you for unions), this approach should lead to DRYer code and cle= aner > abstractions. In the example above, ValidatorNonNegativeInteger and > ValidatorAlphaText can leverage common code in the parent class. And = it is > not necessary to write two separate interfaces in order to handle the = two > different data types. Essentially, it creates a bridge between the ol= d > 'untyped' Zvals and the tightly typed C derivatives. >=20 >=20 >=20 >=20 >=20 > Who Is Going To Write This? >=20 >=20 >=20 > I am relatively new to the PHP community and have never once glanced a= t the > internals of PHP. As much as I would love to do it, my learning curve= will > be quite some time before I would be ready to tackle something like th= is. > And I think the time for this idea is now while there is so much momen= tum > in the community on type-safety. I am considering getting involved in= the > community per the guidance (test writing, documentation, etc) but have= not > plucked up the courage to make the commitment yet. And my C is super > rusty. If this falls on deaf ears, I am afraid the idea will never be= ar > fruit. If everyone thinks it is a good idea, then I am particularly so= rry I > cannot do it myself since it is wrong to make my problem someone else=E2= =80=99s > problem. I would consider writing something in PHP to implement the i= dea, > but cannot really see how it could be accomplished. >=20 >=20 >=20 > Thank you for your time and consideration. And thank you so much for = all > the work you do to make PHP the product that it is. >=20 >=20 >=20 > Kind regards, >=20 >=20 > Doug Wilbourne Hi Doug. Thank you for your interest in PHP. I generally agree with the issues of combining subtype and uses-code-fro= m into a single operation; PHP already has a solution to that, though: T= raits. It's not exactly the same as what you describe, but it's close e= nough for most cases. cf: https://www.garfieldtech.com/blog/beyond-abstract That aside, a change of that scale couldn't happen in PHP 8 at this poin= t. Feature freeze is in less than 2 months and even just figuring out h= ow to implement such a change would take longer than that, even assuming= universal buy in. --Larry Garfield