![](/img/trans.png)
[英]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.