c# - 从基础调用虚方法
问题描述
我正在尝试基于此示例为 MigraDoc 创建一个库,该库支持不同类型的文档。我的想法是制作一个基类,带有一个虚拟方法CreatePage()
(负责页面布局的方法)。但是,概念是CreatePage()
应该从CreateDocument()
用户调用的方法调用。唉,可以覆盖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()
解决方案
由于方法是virtual
,因此将调用正确的版本。起作用的机制称为多态性。
事实上CreateDocument
,它甚至不需要是虚拟的(除非您打算在另一个基类中覆盖它)。
您可以使用一个简单的测试程序来查看它(请注意,我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()
正如预期的那样。
推荐阅读
- java - 实施 Bcrypt PasswordEncoder 后无法使用身份验证
- mysql - 当用户名包含“%”时,无法通过 mysql-workbench 登录 mysql
- mips - MIPS跳转和BNE地址计算
- azure-devops - 如何使用 Azure DevOps/VSTS 和 Ansible playbook 预配环境
- c++ - 如何为以下星形图案添加空间?
- maven - 运行 mvn install 时构建兄弟项目
- php - 如何在 Typo3 9 中检查应用程序上下文?
- php - 代码中的 trans 函数是什么意思……以及 quickadmin 类的位置
- java - JAVA RMI 加法示例
- javascript - 如何从这些属性中构造一个新对象?