2011-07-28 49 views
7

我一直在试图产生应该返回一个通用接口根据输入参数的函数的不同对象(比如Item)(我把它叫做一个上下文)现在getItem(A context)C#中的静态方法的多态性和重载。

一厂,假设我定义了一个新的上下文类型:B,它继承自A

我想返回一个不同的项目,这取决于传递给工厂的对象是否为BA

我试着做如下(重载方法):

class Factory 
{ 
    static Item getItem(A context) {...} 
    static Item getItem(B context) {...} 
} 

这工作得很好,如果我做这样的事情:

B bContext=new B(); 
Item it=Factory.getItem(bContext); 

但是,如果我投和对象类型A

A bContext=(A) new B(); 
Item it=Factory.getItem(bContext); 

第一种工厂方法被调用。

我认为即使在演员演员之后,多态性也能确保第二种方法的执行,并且我想知道我是否遗漏了某些东西?

我知道我可以继续使用单一方法,并使用is运算符来检查变量的类型,但我认为我上面介绍的解决方案更优雅一些。

回答

10

超载在编译时决定(除了在C#4使用动态类型)的基础上的参数的编译时类型 - 在你的最后片段,参数的编译时类型为A ,所以它叫Factory.getItem(A)

只有虚拟方法调用是多态的(使用覆盖),其中目标对象的实际执行时间类型决定调用哪个实现。如果AB有一个虚拟方法(在B中被覆盖)可以通过Factory.getItem调用来处理差异,那很好......否则,您会被动态输入或is之类的东西卡住。

1

你无法实现你假装现在设置事物的方式。

一个选择是在工厂方法中有一些逻辑可以区分参数的类型。笨重,不漂亮,但它的工作原理:

class Factory 
{ 
    static Item getItem(ContextA context) 
    { 
     if (context is ContextB) {...} 
     else {...} 
    } 
} 

另一种选择是使上下文对象负责创建对象。例如:

public class ContextA 
{ 
    .... 
    internal virtual Item CreateItem() { //specific creation logic for ContextA } 
} 

public class ContextB: ContextA 
{ 
    .... 
    internal override Item CreateItem() { //specific creation logic for ContextB } 
} 

现在,你可以这样做:

class Factory 
{ 
    static Item getItem(ContextA context) 
    { 
     return context.CreateItem(); 
    } 
} 

没有,如果你做到以下几点:

ContextA context = new ContextB(); 
Item item = Factory.getItem(context) 

ContextB.CreateItem()将被调用。