Scala如何知道要使用的集合实现?

Vla*_*kov 3 constructor scala scala-collections

val set1 = Set(1,2,3)
Run Code Online (Sandbox Code Playgroud)

要么

val list1 = List(1,2,3)
Run Code Online (Sandbox Code Playgroud)

你能描述这些物体构造背后的精确机制吗?

Java中,我们需要HashSetLinkedList来构造对象.

在这里,我们看到与apply方法一起使用的特征?

这适用于哪种方法?

带有暗示的东西?

Ben*_*ich 5

特征可以有伴侣对象.因此,当您调用时Set(1, 2, 3),您实际上正在调用apply伴随对象上的方法Set.例如,你可以看到Set伴侣对象文件在这里,和它的源代码在这里.

每个集合类型的伴随对象都有一个使用的实例化的默认实现apply.实际上,集合类型的伴随对象都是从抽象类扩展而来GenericCompanion,它封装了这种行为.

这是Scala不可变集合类型层次结构的图像.箭头从AB手段B延伸A,虚线箭头表示B隐式可见为a A,而粗线表示apply伴随对象上的方法A返回实例B.

Scala不可变集合

因此,举例来说,当你打电话Iterable(1, 2, 3),你会得到一个List,因为有从粗线IterableSeqLinearSeqList.您可以在此处阅读有关Scala集合类型层次结构(包括可变版本)的更多信息.

来自Java时,这可能会令人惊讶,但实际上它很有意义.Set例如,在实例化时,您可能不关心实际实现是什么,实际上只是想要Set类型契约的所有保证,并且可以信任该语言来选择实现.

你碰巧Set在你的问题中使用,这稍微复杂一些. Sets少于5个元素具有特殊的效率实现.因此,上图中的粗体箭头仅显示通常情况(足够大Sets).例如:

Set(1, 2, 3, 4, 5).asInstanceOf[HashSet[Int]] // Works as expected
Set(1, 2, 3).asInstanceOf[HashSet[Int]] // Doesn't work!
Set(1, 2, 3).asInstanceOf[collection.immutable.Set.Set3[Int]] // Set3 is the special implementation of sets with example 3 elements.
Run Code Online (Sandbox Code Playgroud)

作为使用集合的最后一点,在这里使用REPL对于确定集合特征的默认实现非常有用(无需参考图表).例如,在这里我们可以看到Iterable伴随对象List按预期构造一个:

Iterable(1, 2, 3)
>>> Iterable[Int] = List(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)