我应该何时使用接口,何时使用基类?
如果我不想实际定义方法的基本实现,它应该始终是一个接口吗?
如果我有狗和猫的课。为什么我要实现IPet而不是PetBase?我可以理解为ISheds或IBarks(IMakesNoise?)提供接口,因为它们可以逐个宠物放置,但我不知道该为普通宠物使用哪个接口。
我应该何时使用接口,何时使用基类?
如果我不想实际定义方法的基本实现,它应该始终是一个接口吗?
如果我有狗和猫的课。为什么我要实现IPet而不是PetBase?我可以理解为ISheds或IBarks(IMakesNoise?)提供接口,因为它们可以逐个宠物放置,但我不知道该为普通宠物使用哪个接口。
当前回答
我有一个粗略的经验法则
功能:可能在所有部分都不同:界面。
数据和功能,部分基本相同,部分不同:抽象类。
数据和功能,实际工作,如果只进行了轻微的修改:普通(具体)类
数据和功能,没有计划的更改:带有最终修饰符的普通(具体)类。
数据,可能还有功能:只读:枚举成员。
这是非常粗略和准备好的,并且根本没有严格定义,但是有一个范围是从所有内容都要更改的接口到所有内容都像只读文件一样固定的enums。
其他回答
除了那些提到IPet/PetBase实现的注释之外,在某些情况下,提供访问器帮助器类可能非常有价值。
IPet/PetBase风格假设您有多个实现,从而增加了PetBase的价值,因为它简化了实现。然而,如果您有多个客户端,则提供一个类帮助来帮助使用接口,可以通过使接口更容易使用来降低成本。
用你自己的判断,要聪明。不要总是照别人(像我)说的做。你会听到“更喜欢接口而不是抽象类”,但这取决于实际情况。这取决于班级。
在上面提到的情况下,我们有一个对象层次结构,接口是一个好主意。接口有助于处理这些对象的集合,在实现服务时也有助于使用层次结构中的任何对象。您只需定义一个用于处理层次结构中的对象的契约。
另一方面,当您实现一组共享公共功能的服务时,您可以将公共功能分离为一个完整的单独类,也可以将其移动到一个公共基类中,并使其抽象化,以便没有人可以实例化基类。
还要考虑如何随时间推移支持抽象。接口是固定的:您将一个接口作为任何类型都可以实现的一组功能的契约发布。基类可以随着时间的推移而扩展。这些扩展成为每个派生类的一部分。
以前关于将抽象类用于公共实现的评论无疑是正确的。我还没有看到提到的一个好处是,使用接口可以更容易地实现用于单元测试的模拟对象。如Jason Cohen所描述的那样定义IPet和PetBase,使您能够轻松模拟不同的数据条件,而无需物理数据库的开销(直到您决定是时候测试真实数据为止)。
现代风格是定义IPet和PetBase。
该接口的优点是其他代码可以使用它,而与其他可执行代码没有任何联系。完全“干净”。界面也可以混合。
但是基类对于简单的实现和通用实用程序很有用。因此,还提供一个抽象基类,以节省时间和代码。
如果除了您的类型成员之外,其他开发人员确实没有任何理由希望使用自己的基类,并且您预见到版本控制问题,那么您应该使用基类(请参见http://haacked.com/archive/2008/02/21/versioning-issues-with-abstract-base-classes-and-interfaces.aspx).
如果继承开发人员有任何理由使用自己的基类来实现类型的接口,并且您没有看到接口发生变化,那么就使用接口。在这种情况下,为了方便起见,您仍然可以加入实现接口的默认基类。