在设计我的软件时,我从接口开始,因为这似乎是“标准”。然后我切换到抽象类,因为它们似乎更适合手头的问题。但是,我不确定在做出此设计选择时是否遗漏了一些注意事项。除了我考虑过的领域特定问题之外,在接口和抽象类之间进行选择时要考虑的更一般的因素是什么?
5 回答
继承定义了组合的相似性。接口定义了行为的相似性。从那里你必须决定组合是否足够重要以覆盖行为。
我发现大多数时候最好的选择是两者都做。当您依赖基类中发生的某些事情时,这并不总是可能的。同时提供抽象基类和接口允许您的抽象实现者拥有最大的自由度,同样,只要您不要求接口的实现者发生某些事情。如果您要求发生某些事情,那么您根本不想提供接口 - 您还需要确保您的基类确保始终发生所需的操作......
对两者都不利:更粘。
示例伪代码:
interface IVehicle
{
void PutCarInGear(Int speed);
}
abstract class Vehicle : IVehicle
{
public void PutCarInGear(Int speed)
{
//base implementation
}
}
请注意,在此示例中,有人可以创建自己的实现类,IVehicle
然后将其传递给任何需要IVehicle
. 该对象不需要是Vehicle
抽象类的子对象。因此,如果您期望在方法中发生特定的事情PutCarInGear()
,那么新类很可能不会满足该期望。但是,只要它IVehicle
的实现无关紧要,那么同时拥有抽象基类和接口是最灵活的抽象。
如果您的接口至少对某些功能还具有合理的默认行为,您可能希望使用抽象类来避免所有具体实现中的通用样板代码。否则,使用接口。
当您有多个具体化模板方法模式的实例时,请使用抽象类。
假设您有三个解析器。一个用“,”分隔文件数据,另一个用“”分隔,另一个用“|”分隔
然后,您可以拥有一个 CommaParser、一个 SpaceParser 和一个 PipeParser,它们都是抽象解析器的子类,并覆盖抽象方法,getDelimiter()
当类不共享实现时使用接口,而只是响应相同的方法调用。
如果它是“是”关系并且应该做子集/所有功能,则将其保留为抽象类。如果它是“应该做”的关系,请将其保留为界面。