2015-10-20 34 views
3

想象我有一个简单的界面:PHP类型提示界面

interface A {} 

然后,我有一些类实现该接口:

class B implements A {} 
class C implements A {} 

然后,我有一个类,它有一个方法,期望B类的对象作为参数(我不能在这里使用接口类型提示,因为只有B类具有D类所需的一些独特功能):

class D 
{ 
    public function foo(B $bar) { /*...*/ } 
} 

不过,我也有同样的方法另一类现在expectes C类对象作为参数(我不能使用的接口类型提示这里是因为只有C类有一些独特的功能,E级要求):

类d和E的
class E 
{ 
    public function foo(C $bar); { /*...*/ } 
} 

和对象必须在其他地方使用,我必须确保这些对象将有法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 
} 

在我看来,这个代码在逻辑上是有效的,因为我们可能有我想在这个职位描述的情况,但我很惊讶看到致命错误与消息:..宣言必须与兼容..

所以我的问题是这样的:如何确保几个对象将有一个SPE cific方法,并且每个对象中的方法只接受特定对象作为参数?

截至目前,我看到的唯一的解决方法是类似如下(,但我相信有这个更好的解决方案):需要具体

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); 
     /*...*/ 
    } 
} 
+3

[此问题](http://stackoverflow.com/q/11493902/1233508)可能会有用。 – DCoder

回答

2

的一个问题是类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(如你的例子),那么你有一个装饰器模式。