如何调用派生类的虚方法?

时间:2011-09-22 08:25:20

标签: c# oop inheritance virtual

我创建了这些类:

public abstract class Node
{
    public virtual NodeModel CreateModel()
    {
        throw new NotImplementedException();
    }
}

public class Folder : Node
{
    public virtual FolderModel CreateModel()
    {
        // Implementation
    }
}

public class Item : Node
{
    public virtual ItemModel CreateModel()
    {
        // Implementation
    }
}

然后在我的程序中,我有一个节点列表,它只包含项目和文件夹对象。当我在列表上循环并尝试调用CreateModel()方法时,这始终是调用的Node类方法(因此抛出异常)。

我无法将CreateModel()更改为abstract,因为返回类型因派生类型而异。我想知道是否有可能有不同的返回类型。我也想避免泛型。事实上,当使用它的实例时,Intellisense向我展示了上层方法。如果我从上层类中删除虚拟实现,那么它将显示基类实现。这是我认为实际上可能的地方。

那么如何强制程序调用上层方法呢?


编辑:答案很简单,就在我的鼻子底下。返回类型无关紧要,因为它将继承自基类抽象CreateModel()中定义的返回类型。我只是在我的基类中将方法标记为抽象,它工作得很好。我不知道为什么我在某些时候感到困惑,因为现在对我来说这似乎很明显。

感谢大家帮助我。

4 个答案:

答案 0 :(得分:2)

在我看来,你的基类应该是通用的,派生类指定适当的类型参数。

public abstract class Node<T> where T : NodeModel
{
    public abstract T CreateModel();
}

public class Folder : Node<FolderModel>
{
    public override FolderModel CreateModel()
    {
        // Implementation
    }
}

public class Item : Node<ItemModel>
{
    public override ItemModel CreateModel()
    {
        // Implementation
    }
}

现在你有一个单个方法,被适当地覆盖 - 而不是方法隐藏,这总是会让人感到困惑。

编辑:如果你想能够在没有泛型的情况下引用它们,你总是可以创建一个非通用的界面,如下所示:

public interface INode
{
    NodeModel CreateModel();
}

public abstract class Node<T> : INode where T : NodeModel
{
    public abstract T CreateModel();

    // Explicit interface implementation so we can implement INode.CreateModel
    // with a different return type. Just delegate to the strongly-typed method.
    NodeModel INode.CreateModel()
    {
        return CreateModle();
    }
}

答案 1 :(得分:1)

C#在函数返回类型中不支持covariance

无论如何,只需将CreateModel()的返回类型指定为NodeModel以外的其他部分,而其他部分依赖于它们更具体,例如:当FolderModel使用更多方法扩展NodeModel时。

如果您只是遍历Node对象列表并调用CreateModel(),则不需要它,只需使用NodeModel返回类型声明Folder.CreateModel(),即使它返回FolderModel。

答案 2 :(得分:0)

这是一个使用类继承而不是泛型的版本:

public abstract class Node 
{ 
    public virtual NodeModel CreateModel() 
    { 
        throw new NotImplementedException(); 
    } 
} 

public class FolderModel : NodeModel
{
  // blah
}

public class Folder : Node 
{ 
    public virtual NodeModel CreateModel() 
    { 
      var node = new FolderModel();
      blah;
      return node; // FolderModel derives from NodeModel
    } 
} 

public class ItemModel : NodeModel
{
  // blah
}

public class Item : Node 
{ 
    public virtual NodeModel CreateModel() 
    { 
      var node = new ItemModel();
      blah;
      return node; // ItemModel derives from NodeModel
    } 
} 

public foo(Node node)
{
  var model = node.CreateModel();
}

model的类型取决于节点的类型。 操纵模型的特定部分必须以某种方式成为了解每个特定模型内部的虚拟节点方法的一部分。

答案 3 :(得分:0)

public abstract class Node
{
    public virtual NodeModel CreateModel()
    {
        throw new NotImplementedException();
    }
}

public class Folder : Node
{
    public virtual FolderModel CreateModel()
    {
        // Implementation
    }
}

这不是方法覆盖,而是超载。

Node node=new Folder();
node.CreateModel();//Of Folder 

要执行此操作,您必须覆盖派生(文件夹)类

中的CreateModel