[英]Implements a abstract method with interface type hint with a concrete typing class
[英]PHP type hint interface in abstract methods and type hint interface's child class in method implementation
想象一下,我有一個簡單的界面:
interface A {}
然后,我有一些實現該接口的類:
class B implements A {}
class C implements A {}
然后,我有一個類,它有一個方法,它希望類B的對象作為參數(我不能在這里使用接口類型提示,因為只有類B具有類D要求的一些獨特的功能):
class D
{
public function foo(B $bar) { /*...*/ }
}
但是,我還有另一個類使用相同的方法,現在將類C的對象作為參數(我不能在這里使用接口類型提示,因為只有類C具有類E需要的一些獨特的功能):
class E
{
public function foo(C $bar); { /*...*/ }
}
並且D類和E類的對象必須在其他地方使用,我必須確保這些對象將具有方法foo
,所以我最終得到以下內容(抽象類在這里不是錯誤,不應該使用接口,因為在現實生活中,這個類也應該包含一些非抽象的方法) :
abstract class DE
{
abstract public function foo(A $bar); // type-hint interface
}
然后我編輯了我的類,所以他們擴展了類DE:
class D extends DE
{
public function foo(B $bar); // class B implements A
}
class E extends DE
{
public function foo(C $bar); // class C implements A
}
在我看來,這段代碼在邏輯上是有效的,因為我們可能會遇到我試圖在這篇文章中描述的情況,但我很驚訝地看到致命錯誤的消息: 聲明......必須與...兼容。
所以我的問題如下: 如何確保多個對象具有特定方法,並且每個對象中的方法僅接受特定對象作為參數?
截至目前,我看到的唯一解決方法是以下內容( 但我相信有更好的解決方案 ):
interface A {}
class B implements A {}
class C implements A {}
interface DE
{
public function foo(A $bar);
}
class D implements DE
{
public function foo(A $bar)
{
assert($bar instanceof B);
/*...*/
}
}
class E implements DE
{
public function foo(A $bar)
{
assert($bar instanceof C);
/*...*/
}
}
一個問題是D類和E類分別需要具體的B類和C類。 既然你應該勸阻類繼承,我會盡量避免在方法簽名中放入具體的類。 如果您的類需要使用具體類,請不要泄漏該信息,請將其保密。
所以最好有:
public function foo(SomethingAbstract $noIdeaWhatIAmButIDoStuff) {
$concrete = SomethingConcreteThatMakesUseOfAbstract($noIdeaWhatIAmButIDoStuff);
}
比:
public function foo(SomethingConcrete $tmi) {
}
我建議按照以下思路思考:
abstract class DE {
public abstract function foo(A $a);
}
class D extends DE {
public function foo(A $a) {
$b = new B($a);
//do with $b what you please
}
}
class E extends DE {
public function foo(A $a) {
$c = new C($a);
//now you can use $c which will leverage $a
}
}
如果B和C對象也需要實現A(就像你的例子中那樣),那么你就有了一個裝飾器模式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.