2012-12-14 147 views
4

为什么我收到此错误:为什么方法声明不兼容?

Fatal error: Declaration of ConcreteFooMapper::load() must be compatible with that of AbstractFooMapper::load() on line 18 

从这个代码:

<?php 
interface Foo { 
    public function foo(); 
} 

class ConcreteFoo implements Foo { 
    public function foo() { 

    } 
} 

abstract class AbstractFooMapper { 
    abstract public function load(Foo $entity, array $data); 
} 

class ConcreteFooMapper extends AbstractFooMapper { 
    public function load(ConcreteFoo $entity, array $data) { 

    } 
} 
?> 

我最初的想法是,这是一个错误; PHP没有检测到 ConcreteFoo implements Foo它在评估方法声明时它。我想这是因为,当您运行此代码:

<?php 
interface Foo { 
    public function foo(); 
} 

class ConcreteFoo implements Foo { 
    public function foo() { 

    } 
} 

$foo = new ConcreteFoo(); 

if ($foo instanceof Foo) 
{ 
    print 'w00t!'; 
} 
else 
{ 
    print 'FAIL!'; 
} 
?> 

它打印 w00t!表示 ConcreteFoo Foo的一个实例。

对此行为是否正确的任何见解?

回答

2

实现接口的类必须使用与接口中定义的完全相同的方法签名。不这样做会导致致命的错误。对扩展抽象类的类也有相同的规则。

请参阅see in details heresee here too

这是正确的行为\逻辑。

check here抽象类型是有用的,因为它们可以用来定义和执行协议;所有实现该协议的对象必须支持的一组操作。

如果我们假设你的代码将无一例外地工作,那么我们有以下的问题:ConcreteFooMapper无法使用的一些class ConcreteFoo2 implements Foo实例作为参数load方法,而应该(通过抽象类定义)

而且,如果你使用相同的签名,这真的不是问题,导致所有类\类型信息可用。请检查以下代码

<?php 
interface Foo { 
     public function foo(); 
} 

class ConcreteFoo implements Foo { 
     public function foo() { 
     } 
} 

abstract class AbstractFooMapper { 
     abstract public function load(Foo $entity, array $data); 
} 

class ConcreteFooMapper extends AbstractFooMapper { 
     public function load(Foo $entity, array $data) { 
       var_dump($entity instanceof Foo); 
       var_dump($entity instanceof ConcreteFoo); 
     } 

} 

$someConcreteFoo = new ConcreteFoo(); 
$someFooMapper = new ConcreteFooMapper(); 

$someFooMapper->load($someConcreteFoo, array('somekey' => 'somevalue')); 
// output 
// bool(true) bool(true) 

?> 
+0

啊。这就说得通了。我希望能够使用类型提示来强制'ConcreteFooMapper'的'load'方法中传递'ConcreteFoo'的实例,但现在我看到了如何破坏协议/协议。 我只是在使用'instanceof'的方法的开头添加类型检入。这是我过去所做的。 – kulishch

3

根据docs,类型提示必须完全匹配。

+0

OK;很高兴我对多态的理解没有错,只是PHP的实现而已。 – kulishch

+2

强化扩展类中的谓词会违反Liskov的替代原则;这可能不是根本原因,但它适用于我:) –

+0

由于方差,它不遵守原则吗? –

相关问题