从基础调用虚拟方法

时间:2018-06-20 08:17:19

标签: c# virtual-method

我正在尝试基于this example为MigraDoc创建一个库,该库支持不同类型的文档。我的想法是使用CreatePage()的虚拟方法(负责页面布局的方法)创建基类。但是,概念是CreatePage()应该从用户调用的CreateDocument()方法中调用。 las,可以覆盖CreatePage(),但这并不意味着直接调用它。看起来像这样:

public class DocumentWriter
{
    private Document document;

    public virtual void CreateDocument(IDocumentArgs args)
    {
       document = new Document();

       DefineStyles();
       CreatePage();
       FillContent(args);
    }

    public virtual void CreatePage()
    {
        // Create page layout here
    }

    // Remaining code skipped for readability...
}

但是如果创建继承了CreatePage()的继承类,那么将从CreateDocument()调用哪个方法?

  • 原始的虚拟(不可覆盖)方法
  • 覆盖CreatePage()的方法

1 个答案:

答案 0 :(得分:5)

由于方法为virtual,因此将调用正确的版本。工作中的机制称为polymorphism

实际上,CreateDocument甚至不需要是虚拟的即可工作(除非您打算在另一个基类中覆盖它)。

您可以在使用simple test program时看到它(请注意,我制作了CreatePage protected,因此不能从DocumentWriter或其基类外部调用它)。请注意,即使当我通过基类类型显式调用CreateDocument时,它也将始终根据对象的运行时类型来调用正确的版本。

public class DocumentWriter
{
    public /*virtual*/ void CreateDocument()
    {
       CreatePage();
    }

    protected virtual void CreatePage()
    {
        System.Console.WriteLine("DocumentWriter.CreatePage()");
    }
}

public class PdfDocumentWriter : DocumentWriter
{
    protected override void CreatePage()
    {
        System.Console.WriteLine("PdfDocumentWriter.CreatePage()");
    }
}

public class HtmlDocumentWriter : DocumentWriter
{
    protected override void CreatePage()
    {
        System.Console.WriteLine("HtmlDocumentWriter.CreatePage()");
    }
}

public static class Program
{
    public static void Main()
    {
        DocumentWriter documentWriter = new PdfDocumentWriter();
        documentWriter.CreateDocument();

        // Re-use the same variable. 
        // CreateDocumentwill still call the correct version of CreatePage.
        documentWriter = new HtmlDocumentWriter();
        documentWriter.CreateDocument();
    }
}

此打印

PdfDocumentWriter.CreatePage()
HtmlDocumentWriter.CreatePage()

符合预期。