I think it'll be much easier to see the problem in a code example than writing the question in the first place. Here is my php code:
<?php
interface AnInterface
{
public function method();
}
class AClass implements AnInterface
{
public function method()
{
echo __METHOD__;
}
}
abstract class AnAbstractClass
{
abstract public function method( AnInterface $Object );
}
class ConcreteClass extends AnAbstractClass
{
public function method( AClass $Object )
{
$Object->method();
}
}
$Object1 = new ConcreteClass();
$Object2 = new AClass();
$Object1->method( $Object2 );
The above code causes the following error:
Fatal error: Declaration of ConcreteClass::method() must be compatible with that of AnAbstractClass::method()
The problem is that php doesn't seem to be recognizing the signatures of AnAbstractClass::method and ConcreteClass::method as compatible. Am I doing something wrong? Thanks!
Does not compute. We had the same discussion yesterday:
Can parameter types be specialized in PHP
All your derived classes must implement the method signatures identically.
This is something that would ideally be checked at runtime. But in PHP the parser does. (To compensate, PHP does not check private/protected attribute access at parsing time, but let that one rather blow up at runtime.)
If you want to enforce a more stringent type, I would advise:
Here's an example that shows, why this is not allowed:
This would be a valid code, but it would fail, if you pass a
ConcreteClass
to moo, because its methodConcreteClass::method
does not allowBClass
.It is complicated, but it is easier to understand, if you see an example.
PHP is correct, they're not compatible. By allowing only instances of
AClass
(or its children) to be passed toConcreteClass::method
, you're breaking the contract thatAnAbstractClass
provides: Any of its subclasses must acceptAnInterface
as an argument to itsmethod()
.If your example worked, and I had another class
BClass
implementingAnInterface
, we'd have a situation where according toAnAbstractClass
,method()
should accept instances ofBClass
, while according toConcreteClass
, it shouldn't.Change your signature for
ConcreteClass::method
to match that ofAnAbstractClass::method
.