【问题标题】:c# runtime polymorphism with abstract base classc# 具有抽象基类的运行时多态性
【发布时间】:2014-10-14 18:25:45
【问题描述】:

我正在尝试清理现有代码库,但在对抽象类的不同派生类使用通用引用名称时遇到了问题。

例如:

public abstract class Base<T> : Utilities.CommonRequiredObject
{
    protected List<T> RawContents = new List<T>();
    .
    .

    public abstract void LoadContents(List<T> Contents);        // Each Class needs to load and process differently
    protected List<T> Contents;

    public virtual void DoSomething()           // Default here for common use. Defined in Each class for its specifics (if needed)
    {
    ...
    }
    public abstract List<T> FunctionToGetContents();

}

public class FOO : Base<string>
{
    public override void DoSomething() ...
    public override List<string> FunctionToGetContents() ...
}

public class BAR : Base<byte>
{
    public override void DoSomething() ...
    public override List<byte> FunctionToGetContents() ...
}

主要逻辑尝试使用公共变量。我想创建一个要使用的新类,但想以运行时多态方式使用它。由于这些类具有通用功能,并且在需要时具有覆盖,我希望能够创建一个实例,然后使用它:

IE: Base<T> ObjectToUse;

这样,我可以简单的参考下面代码中的ObjectToUse,调用常用方法。由于我从另一个基类继承了一些常用例程,我不确定是否可以使用接口。

if(variable)
{
    FOO ObjectToUse = new FOO();
}
else
{
    BAR ObjectToUse = new BAR();
}

ObjectToUse.LoadContents(ObjectToUse.FunctionToGetContents());
ObjectToUse.DoSomething();
...

编辑: 根据我很快收到的 cmets(再次感谢大家)是否会比删除 Generic (Base&lt;T&gt;) 并拥有所有类型 Base() 的类更好,然后我可以将 ObjectToUse 简单地定义为 Base ObjectToUse;我相信。

【问题讨论】:

  • 这行不通。您的课程 Base&lt;string&gt;Base&lt;byte&gt; 没有共同的祖先。
  • 为什么不直接使用接口呢?如果FOOBAR 都实现了IDoSomething,它刚刚声明了一个DoSomething() 方法签名,那么你就可以做生意了。
  • @Sjips 实际上他们确实这样做了(CommonRequiredObject),但这对他没有任何好处。
  • 感谢您的快速帮助。我要避免的是执行与 ObjectToUse 相同的任务。正在执行代码的 if() 中。更多类型,意味着在 if() 结构中重复更常见的代码。也许我可以将 if() 的逻辑移到 Base 类中以返回一个新对象?
  • @BradleyDotNET:是的,你是对的,否则System.Object 将是共同的祖先。我的意思是 Base 和 Base 没有共同的祖先 Base 左右可以共享代码。你的答案解释正确。

标签: c# object polymorphism runtime


【解决方案1】:

这是做不到的。

通过使用需要泛型类型参数的引用,您必须给它一个。您可以在此处使用dynamic,以便在运行时评估该类型,但这是您将获得的最好结果。

即使使用模板方法模式之类的东西,您也需要指定泛型类型参数。如果您只想要 DoSomething 方法,则需要将其提升为更高的基类(或接口),以便您可以持有对 that 类型的引用,并调用它(非-generic) 函数。

对于您的评论,我会采取的解决方案是这样的;将通用代码重构为基类中的模板方法模式。然后让“触发”函数成为来自非泛型基类(或接口)的非泛型继承成员。现在,您可以持有对该类型的引用,并调用模板方法来引发其他调用。

public void DoAwesomeStuff() //inherited from non-generic parent or interface
{
   LoadContents(FunctionToGetContents());
   DoSomething();
}

然后:

IDoesAwesomeStuff ObjectToUse = new FOO();
ObjectToUse.DoAwesomeStuff();

【讨论】:

  • 好的。所以这将移动到 base() 的父级,可能是我的代码中的一个新类,因为 Utilities.CommonRequiredObject 具有在许多地方共享的一些基本功能。 Base :NewBase,然后将常用函数移入 NewBase()。然后 NewBase ObjectToUse() 并调用 ObjectToUse.DoAwesomeStuff()。
  • @StevenScott 为了避免修改您的(可能是常用的)基类,我只需将其添加到接口中,因为您可以多次继承这些。修改基本功能也可以。当然,“中间”基类也可以,尽管我怀疑你是否需要它。
  • @StevenScott 如果您不想使用界面,您编辑的评论会起作用。
  • 感谢您的信息。现在正在努力更改我的代码。我需要一个抽象基类的组合来实现一些常见的功能,并定义要在类中实现的功能,然后是你提到的接口。我的问题是该类仍然需要一些泛型,这就是我在移动/重构代码时遇到的当前问题。
  • @StevenScott 这应该不是问题,只需让您的通用基类实现IDoesAwesomeStuff。也许我们应该去聊天?
猜你喜欢
  • 2011-09-09
  • 1970-01-01
  • 1970-01-01
  • 2011-07-30
  • 1970-01-01
  • 1970-01-01
  • 2016-06-12
  • 2019-12-26
  • 2014-08-16
相关资源
最近更新 更多