簡體   English   中英

抽象方法中的PHP類型提示接口和方法實現中的類型提示接口的子類

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM