php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #52301 signature incompatibility warning when used with interfaces
Submitted: 2010-07-09 17:23 UTC Modified: 2010-07-10 15:02 UTC
From: giorgio dot liscio at email dot it Assigned:
Status: Not a bug Package: Class/Object related
PHP Version: 5.3.2 OS: all
Private report: No CVE-ID: None
 [2010-07-09 17:23 UTC] giorgio dot liscio at email dot it
Description:
------------
hi, test this:

interface A {}
interface X { public function __construct(A $x); }

class A_BASED implements A {}
class X_BASED implements X { public function __construct(A_BASED $x){} }


interface X says that the first parameter of the constructor must be instanceof A

X_BASED implementation has a constructor with first parameter A_BASED

so, this warning is not correct:

Fatal error: Declaration of X_BASED::__construct() must be compatible with that of X::__construct()

because

"A_BASED implements A"


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-07-09 17:53 UTC] johannes@php.net
-Status: Open +Status: Bogus
 [2010-07-09 17:53 UTC] johannes@php.net
class MyClass implements A {}
new X_BASED(new MyClass);

won't be accepted while X says MyClass would be valid as a constructor Parameter -> contract not fullfilled. So PHP's error is correct.
 [2010-07-09 18:13 UTC] giorgio dot liscio at email dot it
hi johannes, please read better my example

interface A {}
interface X { public function __construct(A $x); }

class A_BASED implements A {}
class X_BASED implements X { public function __construct(A_BASED $TESTTEST){} }

interface X
says its constructor first parameter should be "instance of A"

XBASED implements X
says its constructor first parameter should be "instance of A_BASED"
A_BASED as type hint is correct because A_BASED implements A
 [2010-07-09 20:15 UTC] johannes@php.net
interface X guarantees that any A may be passed. You limit it to A_BASED. MyClass is a valid A but no A_BASED, so X_BASED won't accept it, which conflicts with the promise by interface X.
 [2010-07-09 20:54 UTC] giorgio dot liscio at email dot it
but my A_BASED is a valid instance of A too

class A_BASED implements A {}


constructor

__construct(A_BASED $TESTTEST) {}

overrides

abstract __construct(A $TESTTEST) {}

and A_BASED instanceof A === TRUE

so i don't limit anything because all methods required by interface A are implemented in class A_BASED
 [2010-07-09 20:58 UTC] giorgio dot liscio at email dot it
i think it is a bug because with abstract classes works good

abstract class A {}
abstract class X { abstract public function __construct(A $x); } // must be at least A

class A_BASED extends A {}
class X_BASED extends X { public function __construct(A_BASED $x){} } // it is A_BASED, so it satisfy A
 [2010-07-10 15:02 UTC] colder@php.net
Currently, arguments are invariant. And if not, they should be contra-variant, but 
surely not co-variant like you want.

Your subclass is more strict that the super class which is wrong, as any subclass 
should be able to be used as instances of the super class.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat May 04 10:01:32 2024 UTC