php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #67544 Inheritance not working with typehints.
Submitted: 2014-06-30 11:16 UTC Modified: 2014-06-30 17:37 UTC
From: RQuadling at GMail dot com Assigned:
Status: Not a bug Package: *General Issues
PHP Version: 5.4.30 OS: Win7
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: RQuadling at GMail dot com
New email:
PHP Version: OS:

 

 [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

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-06-30 11:24 UTC] 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 17:37 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2014-06-30 17:37 UTC] requinix@php.net
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"
 
PHP Copyright © 2001-2026 The PHP Group
All rights reserved.
Last updated: Thu Oct 08 00:00:02 2026 UTC