1

如果我有几个子类型,每个子类型都继承一个抽象超类,并且这个超类实现一个接口——在实现动态绑定/多态性时,将对象声明为超类类型与接口类型有什么区别?

所以 A,B,C,D 从 S 扩展而来,S 实现了 I。

我可以:

S a = new A();
S b = new B();

或者

I a = new A();
I b = new B();

我倾向于使用接口,但我突然想知道使用超类是否更好,以防你将接口分成两个接口......

4

2 回答 2

4

从打字的角度来看,没有区别。(除非您通过使用反射在运行时内省类型来专门“寻找”......)

从运行时性能的角度来看,没有区别。(除了加载类的时间可能存在一些非常小的差异......在所有实际用例中都可以忽略。)

从代码实现的角度来看,这两种方法各有利弊:

如果您只使用超类(没有接口),您可能可以编写更少的代码。但另一方面是您的代码不太灵活:

  • 您正在以限制您编写新实现的能力的方式尝试实现的外部 API。这个java.io.OutputStream类就是一个典型的例子。因为它是一个类,你必须创建一个子类来实现一个新的流类型,你可能会发现你必须编写子类来覆盖你“继承”的所有基础设施。

  • 一个类只能有一个超类这一事实进一步限制了您使用树形 API 层次结构。

  • 客户端必须在更大程度上针对实现类 API 进行编码......因为这就是全部。而这限制了程序员改变他/她的想法的能力。


底线:如果特定用例不需要您能够做这些事情(现在或将来),那么使用接口没有任何好处。但很少有真正的用例是这样的。而且使用接口的增量实现工作量很小。


我应该补充一点,我不是在问是否使用接口。我猜接口可以用来强迫某人实现方法(并且从不声明为类型)?

嗯,是的。但是抽象方法也可以。这不是使用接口的真正意义。真正的重点是接口:

  • 允许使用类可能的更丰富的类型层次结构,并且
  • 允许独立于实现类编写客户端代码。

我只是问使用接口作为对象类型为多态性带来什么好处?

从打字和性能水平:无 - 见上文。

我想,您可能会争辩说,如果您以跨越实现层次结构的方式使用接口,那么您在客户端级别具有更大的灵活性。我想你可以称之为“多态性的好处”。(相比之下,如果您的接口层次结构完全反映了您的实现类层次结构,那么您可能什么都没有实现……至少就编写的代码而言。)

然而,多态性是达到目的的一种手段,而不是其本身的目标,所以我认为从抽象意义上询问“多态性的好处”是没有意义的。真正的重点是以有意义的方式设计和实现程序,并产生可维护的代码。

于 2012-07-14T01:16:00.167 回答
1

这完全取决于上下文。

实例化代码将只能访问您将变量声明为的接口或类可用的成员。通常目标是限制实例化代码导入的内容。如果它只需要知道 a List,则将其声明为 a List。如果它需要 in 中的方法ArrayList,则将其声明为ArrayList. 不要让实例化代码知道的比它需要的更多。

于 2012-07-14T01:15:34.073 回答