基类VS抽象方法上的空虚方法 [英] Empty virtual method on base class VS abstract methods

查看:82
本文介绍了基类VS抽象方法上的空虚方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在某些情况下,我找不到一个不太具体的问题,所以我将尝试使其变得非常通用。

I couldn't find a question that was not too specific to some case, so I'll try to make this very generic.

我们需要一个提取器库例如,将其分类为一组文档。每个文档都有其特定的属性,但最终都是文档。因此,我们希望为所有这些文件提供通用的提取操作。

We need an extractor base class to a set of documents, for example. Each document has its specific properties, but they're ultimately documents. So we want to provide common extraction operations for all of them.

即使它们都是文档,如我所说,它们还是有些不同。

Even though they're all documents, as I said, they're somewhat different. Some may have some properties, but some may not.

让我们假设我们有 Document 个基本抽象类,以及从中继承的 FancyDocument NotSoFancyDocument 类。
FancyDocument 具有 SectionA NotSoFancyDocument

Let's imagine that we have the Document base abstract class, and the FancyDocument and NotSoFancyDocument classes that inherit from it. The FancyDocument has a SectionA, the NotSoFancyDocument doesn't.

也就是说,您将捍卫实现这一目标的最佳方法是什么?这是两个选项:

That said, what would you defend as the best way of implementing this? Here's the two options:


  • 基类上的空虚方法

  • Empty virtual methods on the base class

基类上的空虚方法将允许程序员仅覆盖对不同类型的文档有意义的方法。然后,我们将在抽象基类上具有默认行为,该行为将为方法返回 default ,例如:

Empty virtual methods on the base class would allow the programmer to only override the methods that make sense for the different types of documents. We would then have a default behavior on the abstract base class, which would be returning the default for the methods, like this:

public abstract class Document
{
    public virtual SectionA GetDocumentSectionA()
    {
        return default(SectionA);
    }
}

public class FancyDocument : Document
{
    public override SectionA GetDocumentSectionA()
    {
        // Specific implementation            
    }
}

public class NotSoFancyDocument : Document
{
    // Does not implement method GetDocumentSectionA because it doesn't have a SectionA
}




  • 具体的空方法或具体方法抛出 NotImplementedException

  • 由于 NotSoFancyDocument 没有具有 SectionA ,但是其他的确实有,我们可以只返回默认值作为其中的方法,否则我们可以抛出 NotImplementedException 。那将取决于程序的编写方式和其他一些东西。我们可以想像这样:

    Since the NotSoFancyDocument does not have a SectionA, but the others do, we could either just return the default for the method in it, or we could throw a NotImplementedException. That would depend on how the program was written and some other things. We could come up with something like this:

    //// Return the default value
    
    public abstract class Document
    {
        public abstract SectionA GetDocumentSectionA();
    }
    
    public class FancyDocument : Document
    {
        public override SectionA GetDocumentSectionA()
        {
            // Specific implementation
        }
    }
    
    public class NotSoFancyDocument : Document
    {
        public override SectionA GetDocumentSectionA()
        {
            return default(SectionA);
        }
    }
    

    OR

    //// Throw an exception
    
    public abstract class Document
    {
        public abstract SectionA GetDocumentSectionA();
    }
    
    public class FancyDocument : Document
    {
        public override SectionA GetDocumentSectionA()
        {
            // Specific implementation
        }
    }
    
    public class NotSoFancyDocument : Document
    {
        public override SectionA GetDocumentSectionA()
        {
            throw new NotImplementedException("NotSoFancyDocument does not have a section A");
        }
    }
    

    我个人认为抽象方法是更好,因为它的意思是嘿,我需要您能够让SectionA成为文档。我不在乎如何。而虚拟方法的意思是嘿,我在这里有此SectionA。如果它对您来说不够好,请随时更改我的获取方式。。

    Personally, I do think that the abstract method approach is better, since it means "Hey, I need you to be able to get a SectionA to be a document. I don't care how." while the virtual method means "Hey, I do have this SectionA here. If it's not good enough for you, feel free to change the way I get it.".

    我确实认为第一个迹象是面向对象编程的味道。

    I do think the first one is a sign of object oriented programming smell.

    您对此有何看法?

    推荐答案

    在这种情况下,基类应该不了解SectionA。派生类应实现该类型所需的额外属性。

    In this case the base class should know nothing of SectionA. The derived class should implement the extra properties that that type needs.

    对于某些操作,无论该类文档的类型如何,另一个类都需要提取信息。在基本类上最好是具有基本实现的虚拟类,并允许派生类在需要时覆盖它(例如, ToPlainText 仅会输出文档的所有部分) c $ c> Document , FancyDocument 可以覆盖实现,也可以输出 SectionA )。

    For certain operations where another class needs to pull information out regardless of the type of document you will want that method on the base class ideally virtual with a basic implementation and allow derived classes to override it if needed (eg ToPlainText which would just output all the sections of a document would be on Document, FancyDocument can override the implementation to also output SectionA).

    对于其他类不关心文档类型但确实关心它是否具有某些属性的实例,请使用接口。 IDocument 将具有所有公共部分,而 Document 将实现它。 IDocumentWithSectionA 将继承 IDocument FancyDocument 的实现。然后,这可以让您派生另一个具有SectionA的 NetherFancyNorNotFancyDocument ,该节也可以实现 IDocumentsWithSectionA

    For instances where another class doesn't care about the type of document but does care if it has certain properties use interfaces. IDocument would have all the common sections and Document would implement it. IDocumentWithSectionA would inheerit IDocument and FancyDocument would implement that. This then lets you derive another NeitherFancyNorNotFancyDocument that has SectionA which can also implement IDocumentsWithSectionA.

    显然,您拥有比 IDocumentWithSectionA 有用的名称,但这取决于用例。

    Obviously You'd have more useful names than IDocumentWithSectionA but that depends on the usecase.

    TL; DR 将抽象类用于所有文档应具有的通用性和某些通用功能,并使用接口作为契约来说明文档的内容。

    TL;DR use the abstract class for what should be common to all documents and some common functionality, use interfaces as the contract saying what a document has.

    这篇关于基类VS抽象方法上的空虚方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆