|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2014-06-30 11:16 UTC] 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
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2026 The PHP GroupAll rights reserved. |
Last updated: Thu Oct 08 00:00:02 2026 UTC |
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.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"