php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #67232 Interface inheritence not possible in interface
Submitted: 2014-05-08 07:17 UTC Modified: 2014-05-09 09:09 UTC
From: r dot van dot bezooijen at factua dot nl Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.4.28 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: r dot van dot bezooijen at factua dot nl
New email:
PHP Version: OS:

 

 [2014-05-08 07:17 UTC] r dot van dot bezooijen at factua dot nl
Description:
------------
when overriding and interface method in another interface it's says they are incompatible with eachother while the overriding method contains a class/interface which is extended from the class/interface defined in the parent

I think its also related to bug report 43200, Although it's not exactly the same problem.

Test script:
---------------
<?php

    interface IVisitee
    {
        public function accept( IVisitor $visitor );
    }

    interface IVisitor
    {
        public function visit( IVisitee $visitee );
    }

    interface IMetadata extends IVisitee
    {
        public function accept( IValidatorVisitor $visitor );
        
        public function findConstraints( $group );
    }

    interface IValidatorVisitor extends IVisitor
    {
        public function validate( $group, $transverse = false, $deep = false );
        
        public function visit( IMetadata $visitee );
    }

Actual result:
--------------
PHP Fatal error:  Declaration of IMetadata::accept() must be compatible with IVisitee::accept(IVisitor $visitor) in /tmp/test.php on line 30
PHP Stack trace:
PHP   1. {main}() /tmp/test.php:0


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-05-08 12:50 UTC] tyrael@php.net
-Status: Open +Status: Not a bug
 [2014-05-08 12:50 UTC] tyrael@php.net
43200 isn't related to this as far as I can see.

I think php is doing the right thing here.
When extending IVisitee, you are trying to change the signature of accept:
IVisitee would accept any class implementing IVisitor, while your IMetadata now would only accept objects implementing IValidatorVisitor, which are only a subset of classes implemting IVisitor.
The Liskov substitution principle defines that "if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program (e.g., correctness).".

Your example breaks LSP, IMetadata can't always replace IVisitee, as the method signature for accept is different (btw same deal with IValidatorVisitor and IVisitor).

At least this is my understanding of the situation.
 [2014-05-09 06:18 UTC] r dot van dot bezooijen at factua dot nl
You are correct about LSP, but if i replace S & T with my class i get this:

{quote}
if S(IMetadata) is a subtype of T(IVisitee), then objects of type T(IVisitee) in a program may be replaced with objects of type S(IMetadata) without altering any of the desirable properties of that program
{quote}
 [2014-05-09 06:21 UTC] r dot van dot bezooijen at factua dot nl
shouldnt this implicate that it should be possible?
 [2014-05-09 09:09 UTC] tyrael@php.net
"then objects of type T(IVisitee) in a program may be replaced with objects of type S(IMetadata) without altering any of the desirable properties of that program"
the typehint of accept() of T and S isn't compatible (eg. S accepts only a subset of what T accepts), so when changing T-s with S your program would/could start throwing E_RECOVERABLE_FATALs about wrong argument passed.
 
PHP Copyright © 2001-2026 The PHP Group
All rights reserved.
Last updated: Wed Oct 07 16:00:02 2026 UTC