php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #72208 Covariant parameter types should be supported
Submitted: 2016-05-12 13:50 UTC Modified: 2016-05-18 12:31 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:0 (0.0%)
From: mbrowne83 at gmail dot com Assigned:
Status: Wont fix Package: Class/Object related
PHP Version: 7.0.6 OS: Ubuntu 14.04.4 LTS
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2016-05-12 13:50 UTC] mbrowne83 at gmail dot com
Description:
------------
It seems that PHP does not support covariant parameter types. It should be possible to override a base class method and make its parameter type more specific. In the code example, the warning message is erroneous (or at least arbitrary) because the code does in fact conform to the Liskov Substitution Principle and is valid OOP.

Test script:
---------------
//example use case from https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#Covariant_method_return_type

class Animal {}
class Cat extends Animal {}

class AnimalShelter {
    function putAnimal(Animal $a) {}
}

class CatShelter extends AnimalShelter {
    function putAnimal(Cat $c) {}
}

Expected result:
----------------
No output

Actual result:
--------------
Warning: Declaration of CatShelter::putAnimal(Cat $c) should be compatible with AnimalShelter::putAnimal(Animal $a) in /vagrant/test.php on line 14

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-05-12 14:27 UTC] requinix@php.net
-Status: Open +Status: Wont fix -Type: Bug +Type: Feature/Change Request
 [2016-05-12 14:27 UTC] requinix@php.net
How much of that Wikipedia entry did you read?

1. As it says, Eiffel is "[unique] among mainstream languages" for its support for covariant parameters.

2. The code does not obey LSP because of exactly what the entry points out: CatShelter needs to support everything that AnimalShelter does. By restricting the parameter to only Cat objects, it *breaks* LSP "which states that objects of subclasses should always be less restricted than objects of their superclass".

function PutDogInShelter(AnimalShelter $shelter) {
    $dog = new Dog(); // class Dog extends Animal
    $shelter->putAnimal($dog);
}

The above code needs to work with all AnimalShelter-type objects, however it will not work with CatShelters.
 [2016-05-12 14:30 UTC] requinix@php.net
Oh, and the entry goes on to mention that generics/templating can help to address the use case. That feature is being considered: https://wiki.php.net/rfc/generics
 [2016-05-12 14:49 UTC] mbrowne83 at gmail dot com
Sorry, I was confused. I noticed that contravariant parameter types are also not supported, but I imagine that was a design decision rather than an oversight. Thank you.
 [2016-05-18 12:31 UTC] bwoebi@php.net
Contravariant parameter types are something to be considered and already are … but they have their own problems (regarding binding-time verification of the type … as classes are currently not autoloaded when just a typehint is encountered, so you cannot check whether there's a relation between two differently named types or not.)
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Wed Oct 21 08:01:23 2020 UTC