【问题标题】:What's the point of using an abstract class? [duplicate]使用抽象类有什么意义? [复制]
【发布时间】:2014-01-15 20:22:03
【问题描述】:

我知道这是一个菜鸟问题,但我还是要问:使用抽象类的目的是什么?

假设我想从 10 个不同的赌博网站中提取数据。所以我创建了一个带有抽象方法的抽象类,并在我的 10 个类中的每一个中覆盖了这些方法(每个网站 1 个 - 因为每个网站都有不同的 DOM)。

抽象类中的方法实际上什么都不做。为什么我不能只为我的 10 个类中的每一个声明一个同名的方法?

Interface 也有同样的问题。

【问题讨论】:

  • 如果你不知道这是做什么用的,请不要使用它
  • 请注意,否决票不是关于这是一个坏问题,而是一个重复的问题。我认为这是一个非常好的问题,但您应该检查该问题是否在问之前被问过。现在,您应该检查引用的重复项。

标签: c# oop interface abstract


【解决方案1】:

这对于OOP(以及其他编程范例)中称为polymorphism 的概念至关重要。在您的示例中,它允许您说出所有这些对象的共同点,虽然实现特定于每个类,但它说所有对象都应该具有它,这是它们的特征。

多态允许人们概括任何共同点,并且通常可以通过提供更高级别的抽象来避免样板代码。 引用自维基百科:

在编程语言和类型论中,多态性(来自希腊语 πολύς,polys,“many, much”和 μορφή,morphē,“formē”,“形式,形状”)是为不同类型的实体提供单一接口。多态类型是一种类型,其操作也可以应用于某些其他类型的值或类型。有几种根本不同的多态性:

  • 如果一个函数根据有限范围的单独指定的类型和组合表示不同的和潜在的异构实现,则称为 ad hoc 多态性。使用函数重载的许多语言都支持 Ad hoc 多态性。

  • 如果代码在编写时没有提及任何特定类型,因此可以透明地与任意数量的新类型一起使用,则称为参数多态。在面向对象的编程社区中,这通常被称为泛型或泛型编程。在函数式编程社区中,这通常简称为多态性。

  • 子类型(或包含多态性)是一个概念,其中一个名称可以表示许多不同类的实例,只要它们与某个公共超类相关。在面向对象编程中,这通常被简称为多态。

【讨论】:

    【解决方案2】:

    不同的方法有几个原因。考虑以下几点:

    public abstract class MyAbstractBaseClass
    {
         String m_url;
         public MyAbstractClass(String url)
         {
             m_url = url;
         }
    
         public abstract String GetSiteData();
    }
    
    public class SiteAGetter : MyAbstractBaseClass
    {
         // ...
         public override String GetSiteData()
         {
         // ...
         }
    }
    

    使用此抽象方法,编译器会强制您在每个重写实现中真正实现 GetSiteData() 方法。当然,您可以将基类中的 GetSiteData 实现为

    public virtual String GetSiteData()
    {
         return null;
    }
    

    但是现在您不需要在派生类中实现该方法,并且您需要确保在调用该方法的每个地方在使用之前返回值都是非空的它。所以基本上防止任何明显的错误对你自己是有帮助的(你不希望任何人编写不实现该方法的派生类)。另外,抽象类不能直接实例化,所以没有人会犯创建基类实例的错误,因为编译器会阻止它。

    接口的用途略有不同:它们可以由不同的、不相关的类实现。因此,如果由于某种原因您无法创建公共基础,但您希望多个类公开相同的接口(= 提供相同的功能)但它们不相关,请使用接口。接口也用于其他原因,例如单元测试环境中的模拟。还有更多,我建议你阅读一些关于它的好书,然后提出更具体的问题。

    【讨论】:

      【解决方案3】:

      您的示例不符合抽象类的真正目的。尝试阅读这样的内容:

      http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html

      【讨论】:

        【解决方案4】:

        它提供了您的程序结构。您可以拥有一个名为 BaseScraper 的抽象基类,然后使用一个名为 scrape() 的方法为要从每个站点抓取的每个站点创建派生类。然后,您可以将每个刮板的一个实例添加到一个数组中,并遍历该数组,在每个实例上调用 Scrape() 以收集数据。如果您想添加另一个站点,您只需要创建另一个实现 Scrape() 方法的派生类并将其添加到您的爬虫数组中。您无需更改任何其他代码,然后会自动合并新的刮板。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-12-27
          • 1970-01-01
          • 2014-10-30
          • 2012-11-29
          • 1970-01-01
          • 2013-08-24
          • 2017-08-15
          • 1970-01-01
          相关资源
          最近更新 更多