Bug #67544 [Opn->Nab]: Inheritance not working with typehints.
| From: | requinix@php.net | 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