C#中的继承与接口[重复]

Posted

技术标签:

【中文标题】C#中的继承与接口[重复]【英文标题】:Inheritance vs. interface in C# [duplicate] 【发布时间】:2011-09-05 12:57:06 【问题描述】:

可能的重复:Interface vs Base classWhen should I choose inheritance over an interface when designing C# class libraries?

所以我正在用 C# 编写我的第一个真正的程序。该程序将从四个不同的网站抓取数据。我的计划是有一个如下所示的父类:

class Scraper

    string scrapeDate(url);
    string scrapeTime(url);
    //&c.

那么我将有四个继承自它的类。

另一种选择是让Scraper 成为一个接口并让四个类实现它。

这些方法有什么区别?

【问题讨论】:

很可能是重复的,而且是一个不费吹灰之力的问题。 这对初学者来说是一个有效的问题,不需要投票。向我投赞成票。 @Bueller:从什么时候开始推广重复问题? @Steven:至少since November of 2010. @Steven:我的意思是,我在某种程度上同意你的看法。我投票将很多个问题作为重复的问题结束,因为我认为最好将答案和信息整合在一个地方。但是你在这里做了几个 cmets 似乎诋毁用户甚至 asking 一个重复的问题,我觉得这没有抓住重点。我们有能力投票结束一个重复的问题的原因是因为这是一个直觉。如果您真的是初学者,您可能知道“继承”和“接口”,但不知道“基类”。术语很难。你可能会错过这个骗局。 【参考方案1】:

接口仅包含方法、委托或事件的签名。方法的实现在实现接口的类中完成。

一个类可以实现多个接口。

一个类只能有一个直接基类。

【讨论】:

【参考方案2】:

如果你有共同的功能,你应该使用继承 - 然后该功能将在所有子类中可用,并且每个子类都可以扩展或覆盖父类代码。

如果您有一些东西在使用您的类,您将使用接口来确保所有类都实现相同的方法和属性,但不一定具有相同的功能。

【讨论】:

【参考方案3】:

主要区别:

接口根本没有实现,而抽象基类可以实现通用功能 一个类只能继承一个基类,但可以实现多个接口

在你的情况下,你所有的爬虫类可能都需要一些共同的特性,所以让它们都继承自一个共同的基类是有意义的

【讨论】:

【参考方案4】:

参考Abstract Class versus Interface。

有一些相似之处和 接口和接口的区别 一个抽象类:

一个类可以实现几个 接口。 一个类只能继承一个抽象 类。

接口不能提供任何代码, 只是签名。 一个抽象类可以提供 完整的默认代码和/或只是 必须覆盖的细节。

接口无法访问 subs, 函数的修饰符, 属性等一切都是假设的 公开 抽象类可以包含访问 subs, 函数的修饰符, 属性

接口用于定义 一个班级的外围能力。在 换句话说,人和车辆都可以 从 IMovable 接口继承。 一个抽象类定义了核心 一个类的身份,它就在那里 用于相同类型的对象。

如果各种实现只共享 方法签名然后最好 使用接口。 如果各种 实现是相同的 并使用共同的行为或状态 那么抽象类更好用。

如果我们向接口添加新方法 然后我们必须追踪所有 接口的实现和 定义新的实现 方法。 如果我们添加一个新方法到 抽象类然后我们可以选择 提供默认实现 因此所有现有的代码 可能会正常工作。

接口中不能定义字段 抽象类可以有字段和 定义的常量

【讨论】:

【参考方案5】:

您在这里所拥有的东西实际上最好用作接口。如果您有一些您希望包含的通用逻辑或一些您希望包含的通用数据成员,那么您将使用基类并从中继承。您正在做的是要求每个孩子实现最少的逻辑集。

【讨论】:

【参考方案6】:

类继承表示“is-a”关系,例如,TankVehicle。如果您的情况至少不符合这一点,请选择接口而不是继承。

如果提议的基类没有为您的方法提供默认实现,这将是选择接口而不是继承的另一个原因。

在 C# 中,您只能从一个类继承,但可以从多个接口继承。这将是另一个选择接口而不是继承的原因。

明白了吗?

【讨论】:

这些都是很好的简单经验法则。【参考方案7】:

接口允许定义常见行为的结构。

如果您可以提取一个或多个特定行为的通用实现,则继承很有用。

基本上,如果多个类以相同的方式抓取日期,则将 scrapeDate 放在基类中是有意义的;否则只使用一个接口并在每个实现你的接口的类中定义特定的 scrapeDate。

【讨论】:

天狮,​​你喜欢吗? C'est pour ça qu'on te voit plus beaucoup sur Developpez... ;)【参考方案8】:

老实说,两者都做。

public interface IScraper

  string ScrapeDate(string url);


public abstract class Scraper : IScraper

  public string ScrapeDate(string url)
  
    // default implementation
  

这两种方式都有优势,但如果不了解您的需求,就很难量化这些优势。但是,没有理由不能两者都做。为您的类提供接口使其也可用于测试目的。

还有其他需要考虑的;如果每个派生类的功能都足够相似,那么简单地使用一个将参数传递给构造函数的类可能会更容易。

【讨论】:

【参考方案9】:

在我看来,如果可能,继承是更好的方法。在基类中实现通用特性有助于确保底层实现是一致的,而实现接口只能保证接口是一致的。尽可能继承是 OOP 三脚架的一环,并限制代码重复。

当我的对象不能或不应该具有公共基类但需要提供类似功能时,我会使用接口。实现公共接口的类可能(并且可能确实)公开额外的功能,可能实现多个接口,等等。

例如:在一个应用程序中,我的数据访问层是围绕“提供者”类构建的,这些类将业务对象和数据库代理对象与数据库隔离开来。在一个实例中,我有一个提供程序与 SQL Server 数据库交互,另一个提供程序用于与 Oracle CRM On Demand(又名Why God Why)进行通信。两者都实现了一个不可知的接口,因此客户端代码不关心它正在处理哪个数据存储,也不关心使用每个数据的怪癖。

Oracle 提供程序通过一组 Web 服务与托管服务器通信,管理连接会话、批处理请求等。SQL 提供程序使用一组存储过程。尽管这两个接口都接受相同的数据类,但 Oracle 提供程序会转换数据以匹配其深奥(简单地说)模式。通过这个实现,我可以轻松添加提供程序以使用 XML 数据存储、不同的 RDBMS 或存根/模拟单元测试。

在这种情况下,这些东西拥有一个通用的基类没有多大意义,而且在某些情况下,这是不可能的。

【讨论】:

以上是关于C#中的继承与接口[重复]的主要内容,如果未能解决你的问题,请参考以下文章

C ++中的抽象类与接口[重复]

Java 接口与接口的多继承关系

在 C# 中实现接口与显式实现接口 [重复]

C#中的抽象类和接口[重复]

C#中的继承与多态还有接口

使用继承的 C# 重载方法调用 [重复]