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