2013-07-10 45 views
2

我一直将收集的数据结构实例化为子实例并通过其父接口声明。例如,声明为父接口并初始化为子实例

Set<E> collection1 = new HashSet<E>(); 
Map<E> collection1 = new HashMap<E>(); 

这是什么原因。子类将继承所有的方法,并且从Java类文档中提到的所有方法都会被覆盖,但是具有相同的含义。那么声明它们的原因是他们的父界面。

任何投入将大大帮助我使我的基础更强。


编辑

感谢您的反馈。我明白了。 但在改变

Set<E> collection1 = new HashSet<E>(); 

Set<E> collection1 = new LinkedHashSet<E>(); 

我们将失去我们的参考我们原来的HashSet的,因为我们宣布为基准设置的新LinkedHashSet。那么这样做有什么意义呢? 如果有什么方法可以在不丢失数据的情况下将旧实现转换为新实现,那么这将有意义。

回答

4

这被称为编码到接口。这基本上是这样做的,以便您可以稍后更改接口的底层实现,而不必在其他地方的代码中进行任何更改。您可以稍后替换任何混凝土实施。

Set<E> collection1 = new LinkedHashSet<E>(); 

期望接口类型的任何方法或代码都可以提供其任何实现类型。

有效的Java第二版,第52项:参照对象通过其接口

如果存在合适的接口类型,那么参数,返回值和领域都应该使用接口类型声明。如果你养成使用接口类型的习惯,你的程序将更加灵活。如果没有合适的接口存在,则通过类引用对象是完全合适的。

这是Liskov substitution principle说:

可替代性是面向对象编程的一个原则。它指出,在一个计算机程序中,如果S是T的一个子类型,那么类型T的对象可以用类型S的对象代替(即,类型S的对象可以代替类型T的对象),而不改变任何该程序的理想属性(正确性,执行的任务等)。

有点我相信是你的代码不应该依赖对象的实现细节,只是它的发布的接口。

+0

也许值得一提的底层实现,也被称为“具体落实”为好。 – Durandal

+0

@MagicMan注意到:) – NINCOMPOOP

1

的编译器将变量作为抽象类型(例如Set,这意味着如果需要的话,你可以在一个新的具体实现后交换(在JDK或你自己的)的各种设置实现之一。

这是良好的编程习惯,因为它降低耦合。

它的正式名称为Liskov substitution principle