C# 中静态方法的多态性和重载

问题描述 投票:0回答:2

我一直在尝试生成一个工厂,该工厂应该根据函数的输入参数(我称之为上下文)返回公共接口的不同对象(比如

Item
getItem(A context)

现在,假设我定义了一种新类型的上下文:

B
,它继承自
A

我想根据传递给工厂的对象是属于

B
类还是
A
类来返回不同的项目。

我尝试执行以下操作(重载方法):

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
运算符来检查变量的类型,但我认为上面提出的解决方案更优雅一些。

c# polymorphism overloading
2个回答
10
投票

重载是在 编译时(除了在 C# 4 中使用动态类型之外)根据参数的编译时类型决定的 - 在最后一个代码片段中,参数的编译时类型是

A
,所以它调用
Factory.getItem(A)

只有虚拟方法调用是多态的(使用overriding),其中目标对象的实际执行时类型来决定调用哪个实现。如果

A
B
有一个虚拟方法(在
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()
将会被呼叫。

© www.soinside.com 2019 - 2024. All rights reserved.