我应该何时使用接口,何时使用基类?
如果我不想实际定义方法的基本实现,它应该始终是一个接口吗?
如果我有狗和猫的课。为什么我要实现IPet而不是PetBase?我可以理解为ISheds或IBarks(IMakesNoise?)提供接口,因为它们可以逐个宠物放置,但我不知道该为普通宠物使用哪个接口。
我应该何时使用接口,何时使用基类?
如果我不想实际定义方法的基本实现,它应该始终是一个接口吗?
如果我有狗和猫的课。为什么我要实现IPet而不是PetBase?我可以理解为ISheds或IBarks(IMakesNoise?)提供接口,因为它们可以逐个宠物放置,但我不知道该为普通宠物使用哪个接口。
当前回答
用你自己的判断,要聪明。不要总是照别人(像我)说的做。你会听到“更喜欢接口而不是抽象类”,但这取决于实际情况。这取决于班级。
在上面提到的情况下,我们有一个对象层次结构,接口是一个好主意。接口有助于处理这些对象的集合,在实现服务时也有助于使用层次结构中的任何对象。您只需定义一个用于处理层次结构中的对象的契约。
另一方面,当您实现一组共享公共功能的服务时,您可以将公共功能分离为一个完整的单独类,也可以将其移动到一个公共基类中,并使其抽象化,以便没有人可以实例化基类。
还要考虑如何随时间推移支持抽象。接口是固定的:您将一个接口作为任何类型都可以实现的一组功能的契约发布。基类可以随着时间的推移而扩展。这些扩展成为每个派生类的一部分。
其他回答
一个重要的区别是,只能继承一个基类,但可以实现多个接口。因此,如果您绝对确定不需要同时继承不同的基类,那么只需要使用基类。此外,如果你发现你的接口越来越大,那么你应该开始把它分成几个逻辑块来定义独立的功能,因为没有规则规定你的类不能实现所有的功能(或者你可以定义一个不同的接口来继承所有的功能)。
还请记住,不要在OO中被卷走(请参见博客),并始终基于所需的行为来建模对象,如果您设计的应用程序中唯一需要的行为是动物的通用名称和物种,那么您只需要一个类animal,而不是世界上每种可能的动物都需要数百万个类。
除了那些提到IPet/PetBase实现的注释之外,在某些情况下,提供访问器帮助器类可能非常有价值。
IPet/PetBase风格假设您有多个实现,从而增加了PetBase的价值,因为它简化了实现。然而,如果您有多个客户端,则提供一个类帮助来帮助使用接口,可以通过使接口更容易使用来降低成本。
如果除了您的类型成员之外,其他开发人员确实没有任何理由希望使用自己的基类,并且您预见到版本控制问题,那么您应该使用基类(请参见http://haacked.com/archive/2008/02/21/versioning-issues-with-abstract-base-classes-and-interfaces.aspx).
如果继承开发人员有任何理由使用自己的基类来实现类型的接口,并且您没有看到接口发生变化,那么就使用接口。在这种情况下,为了方便起见,您仍然可以加入实现接口的默认基类。
接口和基类表示两种不同形式的关系。
继承(基类)表示“is-a”关系。例如,狗或猫是宠物。这种关系始终代表着班级的(单一)目的(结合“单一责任原则”)。
另一方面,接口表示类的其他特性。我将其称为“是”关系,如“Foo是一次性的”,因此C#中的IDisposable接口。