Bug #67544 [Opn->Nab]: Inheritance not working with typehints.

From: Date: Mon, 30 Jun 2014 17:37:23 +0000
Subject: Bug #67544 [Opn->Nab]: Inheritance not working with typehints.
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-186399@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=67544&edit=1 ID: 67544 Updated by: requinix@php.net Reported by: RQuadling at GMail dot com Summary: Inheritance not working with typehints. -Status: Open +Status: Not a bug Type: Bug Package: *General Issues Operating System: Win7 PHP Version: 5.4.30 Block user comment: N Private report: N New Comment: The derived method *isn't* compatible. The Base\Collection::showItem method takes as an argument any class that extends Base\Item. Real\Collection's method takes any class that extends only Real\Item. What it doesn't support that the base declaration does is some other class that inherits from Base\Item and not Real\Item. Such as namespace OtherReal { class Item extends \Base\Item { } } The base method supports using OtherReal\Item but the derived method does not. Thus it is incompatible. Relevant terminology: "Liskov substitution principle" and "contravariance" Previous Comments: ------------------------------------------------------------------------ [2014-06-30 11:24:03] RQuadling at GMail dot com If I have a base layer that does some work ... <?php namespace Base; abstract class Item {} abstract class Collection { public function showItem(Item $Item){ echo get_class($Item); } } namespace Real; class Item extends \Base\Item {} class Collection extends \Base\Collection { public function showItem(\Real\Item $Item) { parent::showItem($Item); } } namespace Usage; $instance = (new \Real\Collection)->showItem(new \Real\Item); ?> This outputs a warning and the result. ----- Strict standards: Declaration of Real\Collection::showItem() should be compatible with Base\Collection::showItem(Base\Item $Item) in C:\ns.php on line 15 Real\Item ----- I know I can block E_STRICT warnings, but this warning to be is incorrect. I cannot see why the type hint is saying that the types are NOT compatible, when they are. ------------------------------------------------------------------------ [2014-06-30 11:16:53] RQuadling at GMail dot com Description: ------------ Type hinting doesn't support inheritance. The error reported says "must be compatible". Well, if I use the \Base\Item typehint for the \Real\Collection\showItem() method, the code runs without error, so the type being passed is fine. But I don't want any old implementation of \Base\Item in the \Real\Collection. I want a \Real\Item which extends from \Base\Item, so, to me, it IS compatible. Using 'interface Collection' and 'implements \Base\Collection' rather than abstracts makes no difference. Just in case there was anything there. Test script: --------------- <?php namespace Base; abstract class Item {} abstract class Collection { abstract public function showItem(Item $Item); } namespace Real; class Item extends \Base\Item {} class Collection extends \Base\Collection { public function showItem(Item $Item) { echo get_class($Item); } } namespace Usage; $instance = (new \Real\Collection)->showItem(new \Real\Item); Expected result: ---------------- Real\Item Actual result: -------------- Fatal error: Declaration of Real\Collection::showItem() must be compatible with Base\Collection::showItem(Base\Item $Item) in C:\ns.php on line 13 ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=67544&edit=1

« previous php.bugs (#186399) next »