2012-12-14 99 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

由於方差,它不遵守原則嗎? –

相關問題