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

Reply via email to