C#中的继承与接口

Hui*_*Hui 27 c# inheritance interface

可能的重复:
接口与基类
在设计C#类库时,何时应该在接口上选择继承?

所以我正在用C#编写我的第一个真正的程序.该计划将从四个不同的网站获取数据.我的计划是让一个父类看起来像这样:

class Scraper
{
    string scrapeDate(url);
    string scrapeTime(url);
    //&c.
}
Run Code Online (Sandbox Code Playgroud)

然后我会有四个继承它的类.

另一种选择是创建Scraper一个接口,并有四个实现它的类.

这些方法有什么区别?

Mat*_*vis 46

类继承表示"is-a"关系,例如a Tank是a Vehicle.如果您的情况至少不符合此要求,请选择继承继承.

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

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

明白了吗?


3Da*_*ave 10

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

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

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

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

在这种情况下,对于这些东西来说,拥有一个共同的基类并没有多大意义,在少数情况下,这是不可能的.


Fly*_*179 7

老实说,两者兼顾.

public interface IScraper
{
  string ScrapeDate(string url);
}

public abstract class Scraper : IScraper
{
  public string ScrapeDate(string url)
  {
    // default implementation
  }
}
Run Code Online (Sandbox Code Playgroud)

无论哪种方式都有优势,但如果不了解您的要求,很难量化.但是,你没有理由不能同时做到这两点.为您的类提供接口使其也可用于测试目的.

还有其他要考虑的事情; 如果每个派生类的功能足够相似,那么简单地让一个类将参数带到构造函数可能会更容易.


Akr*_*hda 6

参考抽象类与接口

接口和抽象类之间有一些相似点和不同点:

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

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

接口不能具有 subs、函数、属性等的访问修饰符,所有内容都假定为 public
抽象类可以包含 subs、函数、属性的访问修饰符

接口用于定义类的外围功能。换句话说,人和车辆都可以从 IMovable 接口继承。
抽象类定义了类的核心标识,用于相同类型的对象。

如果各种实现仅共享方法签名,那么最好使用接口。
如果各种实现属于同一类型并且使用共同的行为或状态,那么最好使用抽象类。

如果我们向接口添加一个新方法,那么我们必须跟踪该接口的所有实现并定义新方法的实现。
如果我们向抽象类添加新方法,那么我们可以选择提供默认实现,因此所有现有代码都可以正常工作。

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