我创建了两个Java接口Tree<T>
和BinarySearchTree<T extends Comparable<T>>
,其中第二个接口扩展了第一个接口。我有BinarySearchTree
的实现,名为LinkedBinarySearchTree
。以下代码显然在编译时抱怨:
Tree<Object> a = new LinkedBinarySearchTree<Object>();
因为LinkedBinarySearchTree
实现了将T
指定为Comparable
类型的接口,而Object
s不是Comparable
。我完全理解这一点,并不构成我的实施问题。
我想要了解的是这种方法在实践中是否有危险。我无法想象这样一种场景,即从Tree
到BinarySearchTree
的数据类型“缩小”会给我一个运行时错误(ClassCastException
,也许?)但是我想确认一下有更多知识渊博的人。从本质上讲,当扩展该界面被认为是不良实践时,是否“缩小”界面所持有的类型,如果是,为什么呢?
答案 0 :(得分:1)
这根本不是一种不好的做法。是否获得ClassCastException
取决于您尝试做什么,而不是实施方法。
“缩小范围”的一个常见情况是,当人们想要专门化某些实现的类型时,从一个共同的基础派生。例如,要实现一些计算器,每次都有不同的返回类型:
public interface Calculator<T> {
public Number calculate(T... arguments);
}
public interface NumberCalculator<T extends Number> extends Calculator<T> {
@Override
public T calculate(T... arguments);
}
public interface IntegerNumberCalculator extends NumberCalculator<Integer> {
@Override
public Integer calculate(Integer... arguments);
}
public interface FloatNumberCalculator extends NumberCalculator<Float> {
@Override
public Float calculate(Float... arguments);
}
上面的参数可以被指定为与<T>
不同的东西,而返回类型可以继续为每个子类设置为<T>
,从而提供比必须返回更好的类型一致性一直是Number
个对象。
答案 1 :(得分:1)
事实恰恰相反 - 这实际上是一种很好的做法。
请记住,使用泛型是一种通过在编译时捕获尽可能多的错误来避免编码错误的技术。通过加强BinarSearchTree
界面的特异性,您实际上使人们更难以意外地滥用它。不仅如此,他们的错误将在编译时被发现。