On Wed, Jun 10, 2020, at 11:16 AM, Doug Wilbourne wrote: > I propose the following language additions: > > > > 1) add three new keywords to the available syntax for class declarations: > 'inherits' and 'subtypes' and 'patterns'. > > > > 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 substitution. > Conversely, the 'subtypes' keyword indicates that if A subtypes B then A > can be substituted anywhere B can be used but 'subtypes' does not imply > 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. > > > > It should be possible to write 'A inherits, subtypes B' and this should > have the same effect as 'A extends B'. > > > > 2) Add two new operators: 'descendentof' and 'subtypeof' that would augment > 'instanceof'. Semantics parallel the class declaration keywords described > above. > > > > > > Benefits: > > > > It would then be possible to write something like the following: > > > > interface ValidatorInterface > > { > > public function validate($x) : bool; > > public function getErrmsg() : string; > > } > > > > abstract class Validator patterns ValidatorInterface > > { > > abstract public function validate($x) : bool; > > > > public function getErrmsg() : string > > { > > return $this->errmsg; > > } > > } > > > > class ValidatorNonNegativeInteger inherits Validator patterns > ValidatorInterface > > { > > public function validate(int $x) : bool { return 0 <= $x; } > > } > > > > class ValidatorAlphaText(string $x) inherits Validator patterns > ValidatorInterface : bool > > { > > return 1 == preg_match('/^[a-zA-Z]+$/', $x); > > } > > > > ValidatorNonNegativeInteger and ValidatorAlphaText cannot be substituted > 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). > > > > 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. > > > > Currently the compiler allows contradictory parameter declaration between > parent and descendant (using 'extends') but produces a runtime error > indicating that the child method's parameter must conform to that of the > parent. Because substitution is not an issue when A inherits B (using > ‘inherits’ as above, not ‘extends’), 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 error. > > > > Along with generics (already being suggested / discussed I think - and > thank you for unions), this approach should lead to DRYer code and cleaner > 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 old > 'untyped' Zvals and the tightly typed C derivatives. > > > > > > Who Is Going To Write This? > > > > I am relatively new to the PHP community and have never once glanced at 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 this. > And I think the time for this idea is now while there is so much momentum > 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 bear > fruit. If everyone thinks it is a good idea, then I am particularly sorry I > cannot do it myself since it is wrong to make my problem someone else’s > problem. I would consider writing something in PHP to implement the idea, > but cannot really see how it could be accomplished. > > > > 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. > > > > Kind regards, > > > Doug Wilbourne
Hi Doug. Thank you for your interest in PHP. I generally agree with the issues of combining subtype and uses-code-from into a single operation; PHP already has a solution to that, though: Traits. It's not exactly the same as what you describe, but it's close enough 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 point. Feature freeze is in less than 2 months and even just figuring out how to implement such a change would take longer than that, even assuming universal buy in. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php