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