为什么Java中的许多Collection类扩展了Abstract类并实现了接口(也是由给定的抽象类实现的)?
例如,类HashSet
扩展AbstractSet
并实现Set
,但AbstractSet
已经实现Set
.
Col*_*ert 32
这是一种记住这个类真正实现该接口的方法.
它不会产生任何不良影响,它可以帮助理解代码,而无需通过给定类的完整层次结构.
Joa*_*uer 11
从类型系统的角度来看,如果类没有再次实现接口,则类将不会有任何不同,因为抽象基类已经实现了它们.
那是真的.
他们确实实现它的原因(可能)主要是文档:a HashSet
is-a Set
.这是通过添加明确的implements Set
到最后,,虽然它不是绝对必要的.
请注意,使用反射实际上可以观察到差异,但是如果HashSet
没有Set
直接实现,我会很难产生一些会破坏的代码.
Boa*_*ann 10
这在实践中可能无关紧要,但我想澄清一下,显式实现接口与通过继承实现接口并不完全相同.不同之处在于已编译的类文件,并且通过反射可见.例如,
for (Class<?> c : ArrayList.class.getInterfaces())
System.out.println(c);
Run Code Online (Sandbox Code Playgroud)
输出显示的是显式实现的接口ArrayList
,按照它们在源代码中编写的顺序,[在我的Java版本中]是:
interface java.util.List
interface java.util.RandomAccess
interface java.lang.Cloneable
interface java.io.Serializable
Run Code Online (Sandbox Code Playgroud)
输出不包括由超类实现的接口,也不包括作为包含的接口的超接口的接口.特别是,Iterable
并且Collection
从上面遗漏,即使ArrayList
隐式实现它们.要找到它们,您必须递归迭代类层次结构.
如果某些代码使用反射并依赖于明确实现的接口,那将是不幸的,但这是可能的,因此集合库的维护者可能不愿意现在改变它,即使他们想要.(有一种观察称为Hyrum定律:"如果有足够数量的API用户,那么您在合同中承诺的并不重要;您系统的所有可观察行为都将取决于某人".)
幸运的是,这种差异不会影响类型系统.表达new ArrayList<>() instanceof Iterable
和Iterable.class.isAssignableFrom(ArrayList.class)
仍计算为true
.
与科林赫伯特不同,我不会买那些关心可读性的人.(每个认为标准Java库都是由无可挑剔的神创造的人,应该把它看作是它们的来源.我第一次这样做时,我对代码格式化和许多复制粘贴块感到震惊.)
我的赌注是迟到了,他们累了,也不在乎.
归档时间: |
|
查看次数: |
4817 次 |
最近记录: |