> -----Original Message----- > From: Fleshgrinder [mailto:p...@fleshgrinder.com] > Sent: Tuesday, April 19, 2016 8:33 PM > To: Zeev Suraski <z...@zend.com>; Larry Garfield > <la...@garfieldtech.com> > Cc: internals@lists.php.net > Subject: Re: [PHP-DEV] Re: Improving PHP's type system > > On 4/19/2016 11:41 AM, Zeev Suraski wrote: > > It could actually implement all of them - the two parents, and the child. > That sounds like a pretty good, explicit way that requires no > introduction of any new syntax, concepts or engine complexity in order > to do what you're describing. This works fine: > > > > interface foo { function foo(); } > > interface bar { function bar(); } > > interface baz extends foo,bar {} > > > > class impl implements foo, bar, baz { > > function foo(){} > > function bar(){} > > } > > > > function sth(baz $b){} > > > > `class impl implements baz {}` is actually already enough here because > `baz` extends `foo` and `bar`.
Yes I know[1] - it was in the context of Larry's point. > This is the only way to solve such situations right now And it's a good one! > but it does not help with primitive types. :( Which is fine. Primitive types can and should get dedicated solutions. There's really no need for allowing over creativity with userland-customized scalar types. > > One thing we could consider is adding some intelligence for these > > cases, and > for interfaces that only extend other interfaces (without adding new > signatures) - a class would be considered to implement that interface > if it implements all of the 'parent' interfaces that the child interface > extends: > > > > class impl implements foo, bar { > > function foo(){} > > function bar(){} > > } > > > > function sth(baz $b){} <-- would work, as impl implements both foo and > bar, and baz does nothing but extending those. > > > > I'm not sure that's necessary, and believe the current mechanisms > > and > syntax satisfy these use cases already, but it's probably a possibility. > > > > That sounds like runtime checked duck typing. > This actually makes the type > system less strict and might have horrific side effects and that is > exactly the opposite of what union/intersection types are meant for: Not at all. I'm pretty sure you misunderstood what I meant. > preventing this. Above code is the same as: > > function sth($b) { > $b->foo(); > $b->bar(); > } > [snip] I believe you think I meant that instead of checking that $b's class actually implements foo and bar, we'd check whether $b has all of the methods needed by foo and bar - which means that theoretically means that it may have methods foo() and bar() but not actually 'officially' implement their respective interfaces. But there's no reason to do it this way and that's not what I meant. Instead, with my proposal, a $b object whose class implements both foo and bar - will automatically be accepted as one that also implements baz. The checks will be conducted at the interface level, not the function list level. In other words, if $b doesn't explicitly implement baz, we'd take a look at 'baz', see it's comprised of foo & bar, and check whether $b's class implements them. At this point, I can't imagine any negative side effect to automatically deducing that an object that implements foo and bar also implements baz (other than a small performance hit, probably roughly the same as the AND union type). Like I mentioned in my original post, I don't necessarily think it's needed - I personally see no reason not to add 'baz' to the list of interfaces impl implements, or as you said, replace foo and bar with baz altogether. In other words, the way I see I, PHP already supports AND union types through interfaces as it is. Thanks, Zeev [1] bit.ly/1NkDmOA