[PHP-DEV] Implementing interface method with child class in parameter def (Bug #42330)
Hello all, I hope the subject is not misleading. Please look at the following code: ?php class A { } class B extends A { } interface C { function foo(A $a); } class D implements C { public function foo(B $b) { } } This code produces a Fatal error: Declaration of D::foo() must be compatible with C::foo(A $a) in /xyz/inheritance.php on line 10 (see http://3v4l.org/l2M0f). I don't get the reason for that behavior (and I could not find any documentation about that, at least not at http://php.net/manual/en/language.oop5.typehinting.php). I have already found https://bugs.php.net/bug.php?id=42330 but Derick's response does not help me and the linked file cannot be accessed anymore. I'd say that it is absolutely legal to define a more specialized type in a child or implementing class, or would this have any bad side effects? Thanks and best regards Christian
Re: [PHP-DEV] Implementing interface method with child class in parameter def (Bug #42330)
On 17 September 2014 15:52, Christian Stoller stol...@leonex.de wrote: Hello all, I hope the subject is not misleading. Please look at the following code: ?php class A { } class B extends A { } interface C { function foo(A $a); } class D implements C { public function foo(B $b) { } } This code produces a Fatal error: Declaration of D::foo() must be compatible with C::foo(A $a) in /xyz/inheritance.php on line 10 (see http://3v4l.org/l2M0f). I don't get the reason for that behavior (and I could not find any documentation about that, at least not at http://php.net/manual/en/language.oop5.typehinting.php). I have already found https://bugs.php.net/bug.php?id=42330 but Derick's response does not help me and the linked file cannot be accessed anymore. I'd say that it is absolutely legal to define a more specialized type in a child or implementing class, or would this have any bad side effects? Thanks and best regards Christian Interesting that you bring this up today, I was literally talking to NikiC about this yesterday. This is what is called a covariant method argument type, and the reason that it is invalid is because if you pass an instance of D, to function that allows anything implementing C, then it would be acceptable to call foo() with an instance of A. The relevant article on wikipedia: https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#Covariant_method_argument_type -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Implementing interface method with child class in parameter def (Bug #42330)
On Wed, Sep 17, 2014 at 8:52 AM, Christian Stoller stol...@leonex.de wrote: Hello all, I hope the subject is not misleading. Please look at the following code: ?php class A { } class B extends A { } interface C { function foo(A $a); } class D implements C { public function foo(B $b) { } } This code produces a Fatal error: Declaration of D::foo() must be compatible with C::foo(A $a) in /xyz/inheritance.php on line 10 (see http://3v4l.org/l2M0f). I don't get the reason for that behavior (and I could not find any documentation about that, at least not at http://php.net/manual/en/language.oop5.typehinting.php). I have already found https://bugs.php.net/bug.php?id=42330 but Derick's response does not help me and the linked file cannot be accessed anymore. I'd say that it is absolutely legal to define a more specialized type in a child or implementing class, or would this have any bad side effects? This is because parameters are not covariant, they are usually invariant or contravariant. Almost certainly you have no clue what that actually means; it's okay, most people don't. Just go read and learn about them and learn for yourself why parameter types are not covariant. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-DEV] Implementing interface method with child class in parameter def (Bug #42330)
On Wed, 2014-09-17 at 16:52 +0200, Christian Stoller wrote: Hello all, I hope the subject is not misleading. Please look at the following code: ?php class A { } class B extends A { } interface C { function foo(A $a); } Here you say any A can be passed at argument class D implements C { public function foo(B $b) { here you say only a subset of A can be passed as argument Thus having function bar(C $c) { $a = new A(); $c-foo($a); } might work or might not work as $c might be an instance of D. Thus breaks the Liskov Substitution Principle http://en.wikipedia.org/wiki/Liskov_substitution_principle doing it the other way round would work interface E { function foo(B $b); } class F implements E { public function foo(A $a) { } } as any B satisfies the is-a requirement compared to A, so everything valid for E::foo() is valid for F::foo(), too. Along with other subtypes to A. johannes -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php
RE: [PHP-DEV] Implementing interface method with child class in parameter def (Bug #42330)
From: Johannes Schlüter [mailto:johan...@schlueters.de] Thus having function bar(C $c) { $a = new A(); $c-foo($a); } might work or might not work as $c might be an instance of D. Thus breaks the Liskov Substitution Principle http://en.wikipedia.org/wiki/Liskov_substitution_principle Oh, now I see. Thanks fort he example, that helped ;) Christian
Re: [PHP-DEV] Implementing interface method with child class in parameter def (Bug #42330)
Christian Stoller wrote (on 17/09/2014): I'd say that it is absolutely legal to define a more specialized type in a child or implementing class, or would this have any bad side effects? Here is a StackOverflow question discussing exactly this issue, which includes why you can't do that with an interface contract, and some suggestions on what you might want to do instead: http://stackoverflow.com/q/21665795/157957 -- Rowan Collins [IMSoP] -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php