Bug #75095 [Opn->Nab]: Interface inheritance not allowed properly
| From: | nikic@php.net | Date: | Sat, 19 Aug 2017 13:06:54 +0000 |
| Subject: | Bug #75095 [Opn->Nab]: Interface inheritance not allowed properly | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-210741@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=75095&edit=1
ID: 75095
Updated by: nikic@php.net
Reported by: adaliszk at gmail dot com
Summary: Interface inheritance not allowed properly
-Status: Open
+Status: Not a bug
Type: Bug
Package: Scripting Engine problem
Operating System: Irrelevant
PHP Version: 7.1.8
Block user comment: N
Private report: N
New Comment:
Under the Liskov substitution principle argument types are contravariant, not covariant. Please see
https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)
for more information.
Previous Comments:
------------------------------------------------------------------------
[2017-08-19 12:52:12] adaliszk at gmail dot com
Description:
------------
It seems that the engine not using inheritance properly with paramether types in abstract classes
(which would be solved in 7.2) and in interfaces.
The engine seems not seeing that a sub-interface is compatible with the base interface it just may
have more functionalities but the expected boundries are meet even if you override a function method
with a sub-interface of the specified function paramether.
You can bypass this to write the same code without using inheritance or checking the entity type
inside your class:
- The first bypass solution is just not great, since if your collection base
got new functionalities or refactored for some reason, then you have to
copy-paste trough all of your collection interfaces, it's not efficient.
- The second bypass solution is making a joke from the engine typecheck
features, since it has a power to check the input types, but you cannot use
it and you have to write typecheck manually which way you have to write
more code.
It would be great if the engine allow us to override with compatible types the method signitures
like it will allow it with abstract classes and interfaces are abstract classes with only abstract
methods in it.
Test script:
---------------
An example for this: Create a Collection interface and Entity interface where Entities could
add/remove to it. Create sub-interfaces with more functionalities and override the collection
add/remove so it would only allow a sub-interface instead a globaly used one.
// Base interfaces
interface Entity {
public function getId(): int;
}
interface Collection {
public function add(Entity $item): void;
public function remove(Entity $item): void;
}
// just more functionality
interface ProductEntity extends Entity {
public function getName(): string;
}
/// override the types with a subtype, which is compatible by LSP
interface ProductCollection extends Collection {
public function add(ProductEntity $item): void;
public function remove(ProductEntity $item): void;
}
Expected result:
----------------
No errors because the sub-interfaces are compatible with the base interface using Liskov Substitute
Principle.
Actual result:
--------------
Declaration are not compatible error.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=75095&edit=1