这可能是一个通用的OOP问题。我想在接口和抽象类的使用基础上做一个通用的比较。
什么时候需要使用接口,什么时候需要使用抽象类?
这可能是一个通用的OOP问题。我想在接口和抽象类的使用基础上做一个通用的比较。
什么时候需要使用接口,什么时候需要使用抽象类?
当前回答
纯粹在继承的基础上,你可以使用一个抽象的定义清晰的后代,抽象的关系(例如动物->猫)和/或需要继承虚拟或非公共属性,特别是共享状态(接口不支持)。
你应该尝试使用组合(通过依赖注入)而不是继承,并且注意接口作为契约支持单元测试、关注点分离和(语言变化)多重继承,而抽象则不能。
其他回答
基本的经验法则是:对于“名词”使用抽象类,对于“动词”使用接口
例如:car是一个抽象类和驱动器,我们可以让它成为一个接口。
如果下列语句适用于您的情况,请考虑使用抽象类:
您希望在几个密切相关的类之间共享代码。 您希望扩展抽象类的类具有许多公共方法或字段,或者需要除public以外的访问修饰符(例如protected和private)。 您希望声明非静态或非final字段。这使您能够定义可以访问和修改其所属对象状态的方法。
如果这些语句适用于您的情况,请考虑使用接口:
您希望不相关的类实现您的接口。例如,Comparable和Cloneable接口是由许多不相关的类实现的。 您希望指定特定数据类型的行为,但不关心由谁实现其行为。 您希望利用多个继承。
源
好吧,我自己刚刚“grokup”了这个——这是外行的术语(如果我错了,请随意纠正我)——我知道这个话题太老了,但其他人可能有一天会偶然发现它……
抽象类允许你创建一个蓝图,并允许你额外构造(实现)属性和方法,你希望它的所有后代都拥有。
另一方面,接口只允许您声明希望在实现它的所有类中存在具有给定名称的属性和/或方法——但不指定应该如何实现它。同样,一个类可以实现许多接口,但只能扩展一个抽象类。界面更像是一种高级架构工具(如果你开始掌握设计模式,这一点就会变得更清楚)——抽象则同时涉足这两个阵营,也可以执行一些繁琐的工作。
为什么使用其中一种而不是另一种呢?前者允许对后代进行更具体的定义,而后者允许更大的多态性。最后一点对最终用户/编码器很重要,他们可以利用这些信息以各种组合/形状来实现A.P.I(界面),以满足他们的需求。
我认为这对我来说是一个“顿悟”的时刻——少从作者的角度来考虑接口,多从后面加入到项目中实现或扩展API的编码器的角度来考虑接口。
我为此写了一篇文章:
抽象类和接口
总结:
当我们谈论抽象类时,我们是在定义对象类型的特征;指定对象是什么。
当我们谈论接口和定义我们承诺提供的功能时,我们谈论的是建立一个关于对象可以做什么的契约。
我的观点是:
接口基本上定义了一个契约,任何实现类都必须遵守(实现接口成员)。它不包含任何代码。
另一方面,抽象类可以包含代码,并且可能有一些标记为抽象的方法,继承类必须实现这些方法。
我很少使用抽象类的情况是,当我有一些默认功能时,继承类可能对重写不感兴趣,比如一个抽象基类,一些专门的类继承自它。
示例(非常基本的一个!):考虑一个名为Customer的基类,它具有抽象方法,如CalculatePayment(), CalculateRewardPoints()和一些非抽象方法,如GetName(), SavePaymentDetails()。
像RegularCustomer和GoldCustomer这样的专门的类将继承自Customer基类,并实现它们自己的CalculatePayment()和CalculateRewardPoints()方法逻辑,但是重用GetName()和SavePaymentDetails()方法。
您可以向抽象类(即非抽象方法)添加更多功能,而不会影响使用旧版本的子类。然而,向接口添加方法会影响实现它的所有类,因为它们现在需要实现新添加的接口成员。
具有所有抽象成员的抽象类类似于接口。