在接口和抽象类之间进行选择时要考虑哪些因素?
在设计我的软件时,我从界面开始,因为这似乎是“标准”。然后我转向抽象类,因为它们似乎更适合手头的问题。然而,我不确定在做出这个设计选择时是否错过了一些考虑因素。除了我考虑过的领域特定问题之外,在接口和抽象类之间进行选择时还需要考虑哪些更一般的因素?
When designing my software, I began with interfaces since this seems to be the "standard". Then I switched to abstract classes because they seem better suited to the problem at hand. However I'm not sure if I've missed out on some considerations when making this design choice. Other than domain specific issues which I have thought about what are the more general factors to consider when choosing between interfaces and abstracts classes?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我发现大多数时候最好的选择是两者都做。当您依赖于基类中发生的事情时,这并不总是可能的。 同时提供抽象基类和接口可以为抽象的实现者提供最大的自由度,只要您不要求接口的实现者发生任何事情。如果您要求发生某些事情,那么您根本就不想提供接口——并且您还需要确保您的基类确保满足这一要求总是发生的行动...
两者都做的负面影响:更多的粘性。
示例伪代码:
请注意,在此示例中,某人可以创建自己的实现
IVehicle
的类,然后将其传递给任何采用IVehicle
的对象。该对象不需要是Vehicle
抽象类的子类。因此,如果您期望在PutCarInGear()
方法中发生特定的事情,那么该新类很可能无法满足该期望。然而,只要 IVehicle 的实现做什么并不重要,那么同时拥有抽象基类和接口就是最灵活的抽象。I find the best option most of the time is to do both. That is not always possible when you are relying on something happening in the base class . Providing both an abstract base class and an interface allows the greatest latitude by implementers of your abstraction, again, as long as you don't require something happens by an implementer of the interface. If you require that something happens, then you don't want to provide an interface at all--and you would also need to make sure that your base class ensures this required action to ALWAYS occur...
Negative to doing both: more goo.
example pseudocode:
Note that in this example, someone could make their own class that implements
IVehicle
and then pass it to anything that takes anIVehicle
. That object would NOT need to be a child of theVehicle
abstract class. If, therefore, you were to expect something specific to happen in thePutCarInGear()
method, it's quite likely that that new class would NOT fulfill that expectation. However, as long as it never matters what implementations ofIVehicle
do, then it's the most flexible abstraction to have both an abstract base class AND an interface.继承定义了组合的相似性。接口定义行为的相似性。从那里你必须决定构图是否重要到足以覆盖行为。
Inheritance defines similarity of composition. Interfaces define similarity of behavior. From there you have to decide if the composition is important enough to override the behavior.
如果您的接口至少对于某些功能也具有合理的默认行为,您可能需要使用抽象类来避免所有具体实现中的常见样板代码。否则,请使用接口。
If your interface also has reasonable default behavior for at least some of the functionality, you may want to use an abstract class to avoid common boilerplate code in all of the concrete implementations. Otherwise, use an interface.
当您有多个具体化模板方法模式的实例时,请使用抽象类。
假设您有三个解析器。一种用“,”分隔文件数据,另一种用“”分隔文件数据,另一种用“|”分隔文件数据。
然后,您可以拥有一个 CommaParser、一个 SpaceParser 和一个 PipeParser,它们都是 Abstract Parser 的子类,并重写抽象方法
getDelimiter()
当类不共享实现而只是响应时,请使用接口到相同的方法调用。
Use an abstract class when you have multiple instances that reify the Template Method pattern.
Say you have three parsers. One deliminates the file's data by ",", another by " ", and another by "|"
You can then have a CommaParser, a SpaceParser and a PipeParser, all subclassing the Abstract Parser, and overriding the abstract method,
getDelimiter()
Use an interface when the classes don't share implementation, but merely respond to the same method calls.
如果它是“是”关系并且应该执行子集/所有功能,则将其保留为抽象类。如果它是“应该做”的关系,请将其保留为接口。
Keep it as a Abstract Class if its a “Is a” relationship and should do subset/all of the functionality. Keep it as interface if its a “Should Do” relationship.