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

本文关键字:重载 多态性 静态方法 | 更新日期: 2023-09-27 18:03:54

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

现在,假设我定义了一个新的上下文类型: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#中静态方法的多态性和重载

重载是在编译时(除了在c# 4中使用动态类型之外)根据参数的编译时类型决定的——在上一个代码片段中,参数的编译时类型是A,因此它调用Factory.getItem(A)

只有虚方法调用是多态的(使用覆盖),其中目标对象的实际执行时类型决定调用哪个实现。如果AB有一个虚拟方法(在B中被覆盖)可以被Factory.getItem调用来处理差异,那就太好了……否则你只能使用动态类型或者is之类的东西。

你不可能实现你现在所做的一切。

一种选择是在工厂方法中使用一些可以区分参数类型的逻辑。笨拙,不漂亮,但它工作:

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()将被调用