如何在接口和抽象类之间进行选择?

几年来,我一直在采访中问这个问题。我听到了很多有趣的答案。所有这些答案都帮助我增加了自己的知识。如果您搜索该主题,则会发现很多有趣的文章。MSDN上的这篇文章对此主题进行了很好的讨论。为了总结那里的建议以及我所见过的其他几篇文章,以下是赞成抽象类的原因:

  1. 如果您具有子类不必实现的某些行为的默认实现,则请使用抽象类
  2. 如果您的合同有可能随时间变化,则最好选择抽象类。因此,如果您正在使用抽象类,并且需要向抽象类中添加新方法,则可以在不破坏使用该类任何代码的情况下,愉快地添加它。接口并非如此。

这些就是支持接口的原因

  1. 由于C#不支持多重继承,因此您不能从两个抽象类继承您的类。在这种情况下,接口是您唯一的选择。
  2. 如果从抽象类继承的所有类之间没有默认或通用行为,则接口可能是一个更好的选择。

我个人不认为这些可以提供完整的信息。

这种推理有什么问题?

首先,以上建议主要针对特定语言支持的语法,而不是语义(例如,如果需要多重继承,请使用接口)。我所说的语义是指,接口的定义与抽象类的根本区别是什么?
其次,我认为上述标准过于未来主义。我的意思是,它们都取决于您是否知道您的设计将来会如何成形。有时候,我可能对我的设计将来会如何形成有一些想法,但是大多数时候,我没有足够的清晰度来提前知道

  1. 我是否需要从多个抽象类继承
  2. 是否将默认执行某些合同
  3. 我是将新方法添加到合同中还是完全定义新合同以实施更改

因此,如果您不知道软件的发展方向,则无法基于这些原因来决定接口或抽象类的决定。

那么我们如何决定呢?

最近,我一直在使用下面的启发式方法来确定何时使用接口/抽象类,由于它在大多数情况下都起作用,对此我感到非常兴奋。

接口代表功能,抽象类代表类型

换一种说法

实现接口表示可以执行的关系,而从(抽象)类继承则表示is-a关系

为了详细说明这一点,让我们考虑以下两个类

public class Camera 
{ 
  public void Shoot() 
  { 
    //Take a picture here 
  } 
} 
 
public class Gun 
{ 
  public void Shoot() 
  { 
    //Hit the target 
  } 
}
 

CameraGun都能射击,这就是它们的能力。但是它们不是同一类事物,它们是完全不同的。所以像下面这样的界面在这里更有意义

public interface IShootable 
{ 
  void Shoot(); 
} 
 
public class Camera : IShootable 
{ 
  public void Shoot() 
  { 
    //Take a picture here 
  } 
} 
 
public class Gun : IShootable 
{ 
  public void Shoot() 
  { 
    //Hit the target 
  } 
}
 
 

如果您以与我相同的方式学习了OO编程,那么您会记得下面的经典形状示例

public abstract class Shape 
{ 
  void Draw(); 
} 
 
public class Rectangle : Shape 
{ 
  public void Draw() 
  { 
    //Draw a rectangle here 
  } 
} 
 
public class Circle : Shape 
{ 
  public void Draw() 
  { 
    //Draw a circle here 
  } 
}
 
 

从Shape中继承RectangleCircle在这里非常有意义,因为Rectangle/CircleShape的一种类型。

最后

随着软件的增长和新功能的涌现,旧功能不断变化,您可能会对自己说:“哦,天哪,我不应该在这里使用抽象类”。与其试图预测谁将重用哪些代码的特性,不如关注于确定它是抽象出来的功能还是公共类型。如果你觉得这条思路很困难,那就弄清楚你想要建立的是一种“我能行”的关系,还是一种“我能行”的关系。

原文链接:https://dev.to//suhas_chatekar/how-do-you-choose-between-an-interface-and-abstract-class

你可能感兴趣的:(如何在接口和抽象类之间进行选择?)