什么被认为是一般的最佳实践:
通过超级类型引用?
public class BirdFeeder{
public Feed(Bird bird){...}
}
或通过界面
public class BirdFeeder{
public Feed(IBird iBird){...}
}
就我个人而言,我更喜欢接口,但我不太清楚为什么,对我来说他们只是觉得'更干净'。我想更好地理解为什么我会选择一个而不是另一个。
由于
答案 0 :(得分:2)
您对接口是正确的,它们为您设计继承层次结构提供了更大的灵活性。
假设您有一个以基类Bird
开头的层次结构,并继续向各种鸟类开始。现在假设您想要将机械鸟添加到鸟类的层次结构中,但您宁愿从Robot
基类派生它。如果你的喂食器需要Bird
个参数,你的机械鸟需要一个特殊的喂食器。但是,如果馈线采用IBird
,只要它正确实现RoboBird
接口,就可以向其发送IBird
没有问题。
答案 1 :(得分:1)
如果通过“超级类型”和你对接口的比较,我猜你想要专注于基础抽象类。 (尽管你可以使用非抽象的基类,但是一般来说,即使是没有抽象成员的抽象类也倾向于向开发人员传达它本来要实现/继承的东西,而不是作为一个类型独立存在)
基础/抽象类与接口没有全面的“最佳实践”。他们都在设计实践中占有一席之地。实际上,最佳实践来自您正在实施的设计。
当涉及到设计考虑时,最大的区别可能是基类/抽象类只能被继承,而接口可以在任何类的类上实现。
(编辑:pilotcam提出了一个更好的例子,见他对这个问题的评论)
从你的鸟类例子来说,例如你想要处理像鹦鹉,信天翁和企鹅这样的不同鸟类,它们都来自Bird
。但是,您的应用程序也会处理Dinosaur
类型。您可以实施Archaeopteryx。它是继承自Dinosaur
还是来自Bird
?现在,如果Bird
是一个界面,您可以只使用class Archaeopteryx : Dinsoaur, IBird
。这个例子有点做作(我确定这是一个更好的例子),但希望它足够好。
当然,基础/抽象类也很好。例如,通过组合访问修饰符,您可以利用可能实现API访问实现的internal
方法,但类的外部使用者不能。
使用其中一个实际上有很多理由,而且没有一个真正“更好”地编码。这实际上取决于你的应用程序设计,可以说是你编写的比喻;这些物体代表什么。你的对象实际上是是一只鸟,还是只有像鸟一样行事?你的API关心吗?什么会更好地维护你的工作?
这里有更多阅读: Interface vs Abstract Class (general OO)(注意所有与此相关的“相关”类似问题)
答案 2 :(得分:1)
如果要在后代组件中实现一组行为,请使用抽象类。
当您想要在没有有用的共同祖先的许多类上实现一组行为时的接口。
当你可以使用任何一种时,有很多情况。总的来说,我发现我可以重新设计一个使用接口的设计,获得新的东西,而不是陷入一系列可怕的妥协。我宁愿定义一个接口,然后有一个抽象类为它的后代实现它而不是没有接口。这在开始时是一项微不足道的额外工作,可以在以后获得巨大的好处。