因此,我知道对接口进行编码(使用接口作为变量的声明类型而不是其具体类型)在 OO 代码中是一种很好的做法,原因有很多。这在 Java 集合中很常见。那么,当只有该接口的某些实现提供正确的行为时,在您的程序中引用一个接口仍然是一件好事吗?
例如,我有一个 Java 程序。在那个程序中,我有多组对象。我选择使用 Set,因为我不想要重复的元素。但是,我想要一个列表的排序属性(即维护插入顺序)。因此,我使用 LinkedHashSet 作为具体的 Set 类型。这些集合的用途之一是计算涉及集合中包含的对象的原始字段的点积,例如(简化一点):
double dot(LinkedHashSet<E> set, double[] array) {
double sum = 0.0;
int i = 0;
for(E element : set) {
sum += (element.getValue()*array[i]);
}
return sum;
}
此方法的结果取决于集合的迭代顺序,因此某些 Set 实现,主要是 HashSet,将给出不正确/意外的结果。目前,我在整个程序中使用 LinkedHashSet 作为声明的类型,而不是 Set,以确保正确的行为。然而,这在风格上感觉很糟糕。在这里做什么是正确的?在这种情况下可以使用具体类型吗?或者也许我应该使用 Set 作为类型,然后在文档中说明哪些实现将/不会产生正确的行为?我正在寻找更多的一般输入,而不是特定于上述场景的任何内容。特别是,这应该适用于您使用 LinkedHashSet 或 TreeSet 的排序属性的任何场景。您如何防止使用意外的实现?你是在代码中强制它(通过放弃接口),还是在文档中指定它?或者也许其他一些方法?