我有一段代码,其中一些类正在实现一个接口。
感觉是正确的,但是子类之间有一点重复——即 3 个方法。
所以这是尖叫着使用抽象类。
我的问题是,在以下情况下同时使用抽象类和接口会有什么缺点:
- 实现接口的抽象类和扩展抽象类的子类
- 子类扩展抽象类并实现接口
或者
抽象类和接口不应该像这样一起使用吗?
我有一段代码,其中一些类正在实现一个接口。
感觉是正确的,但是子类之间有一点重复——即 3 个方法。
所以这是尖叫着使用抽象类。
我的问题是,在以下情况下同时使用抽象类和接口会有什么缺点:
或者
抽象类和接口不应该像这样一起使用吗?
这两个一起使用是完全正常的。例如考虑JDK 中的AbstractList
(implementing List
) 和AbstractMap
(implementing Map
)。
我的下意识反应是让抽象类实现接口,然后让具体类从中派生:
abstract class Base implements TheInterface {
/* ...shared methods... */
}
class Concrete1 extends Base { }
class Concrete1 extends Base { }
但是你提出另一种可能性的问题让我思考,我看不出有太多反对这样做的论据:
abstract class Base {
/* ...shared methods... */
}
class Concrete1 extends Base implements TheInterface { }
class Concrete1 extends Base implements TheInterface { }
此外,我可以看到这样做的一个论点,特别是它消除了抽象类和接口之间的耦合。如果您有另一个需要Base
提供功能但不需要实现接口的类,您可以灵活地执行此操作。
还有第三种选择:组合。你根本不能有一个抽象类,而是让多个实现接口的具体类在它们的实现中使用一个通用的帮助类:
class Helper {
/* ...shared methods... */
}
class Concrete1 implements TheInterface {
/* ...uses instance of Helper */
}
class Concrete1 implements TheInterface {
/* ...uses instance of Helper */
}
这以另一种形式具有相同的灵活性。
我不认为有这样的经验法则。在设计时,请尝试遵循 SOLID 原则,以确定您所做的事情是好是坏。你可以在这里找到这些原则。在这种特殊情况下,我认为您应该确保遵守“开闭原则”。
我个人更喜欢抽象类是其他类的背景的说法,所以如果其他三个类有共同点,那么它们的共同祖先,即仅为这三个其他类创建的抽象类,也应该提供来自接口的代码。这将使抽象类“完整”(以它的方式)提供三个类共享的所有这些属性和方法。
但是,如果它们都实现相同的接口,最终没有区别。在我看来,让抽象类赋予所有常见的东西是一种更清晰的方式。然后通过仅查看不同之处来比较类更容易。