当你计算表达式时到底会发生什么:Seq(1,2,3)
?
在斯卡拉中,foo(bar)
是语法糖foo.apply(bar)
, 除非this
还有一个名为foo
,在这种情况下,它是隐式方法调用this
接收者,即就像Java一样,它相当于this.foo(bar)
.
就像任何其他 OO 语言一样,方法调用的接收者alone决定如何处理该调用,因此在这种情况下,Seq
决定要做什么。
Seq 是一种特质,对吗?
那里有两个Seq
标准库中的s:
- The trait Seq,这是一个type.
- The object Seq,这是一个value.
所以当你这样称呼它时Seq(1,2,3)
它一定是某种伴生对象吗?或不?
是的,它必须是一个对象,因为您只能调用对象上的方法。您无法调用类型上的方法,因此,当您看到方法调用时,它must成为一个物体。总是。所以,在这种情况下,Seq
不可能 be the Seq
特质,一定是Seq
object.
请注意,“它必须是某种伴生对象”是不正确的。从那段代码中你唯一能看到的是Seq
是一个对象。您无法从该代码段知道它是否是伴生对象。为此,您必须查看源代码。在这种特殊情况下,事实证明is,事实上,一个伴随对象,但您无法从您显示的代码中得出结论。
它是某种扩展 Seq 的类吗?
No. It 不可能是一个类,因为你只能调用对象的方法,而类不是 Scala 中的对象。 (这与 Ruby 或 Smalltalk 不同,其中类也是对象和实例Class
类。)它must成为一个物体。
最重要的是返回值的类型是什么?
找出这一点的最简单方法就是简单地查看Seq.apply 的文档:
def apply[A](elems: A*): Seq[A]
创建具有指定元素的集合。
-
A
:集合元素的类型
-
elems
:创建的集合的元素
-
returns包含元素 elems 的新集合
所以,正如你所看到的,返回类型Seq.apply
is Seq
,或更准确地说,Seq[A]
, where A
是一个类型变量,表示集合元素的类型。
是 Seq 吗?如果是,为什么不显式地使用扩展类?
因为没有扩展类。
此外,Scala 中的标准设计模式是apply
伴生对象的方法返回伴生类或特征的实例。打破这个惯例将会是奇怪和令人惊讶的。
同样在 REPL 中,我看到计算表达式的内容实际上是一个 List(1,2,3),但类型显然是 Seq[Int]。
The 静态类型 is Seq[Int]
。这就是您需要知道的全部。这就是你的全部can know.
Now, Seq
is a trait
,并且特征无法实例化,因此运行时类型将是某个子类Seq
。但!您不能也不能关心它是什么特定的运行时类型。
为什么不是像 Vector 这样的 Indexed 集合类型?这一切背后的逻辑是什么?
你怎么知道它不会返回Vector
下次你打电话的时候吗?这一点都不重要,因为静态类型是Seq
因此你只能打电话Seq
方法,并且您只能依赖于合同Seq
, i.e. Seq
无论如何,后置条件、不变量等等。甚至if你知道这是一个Vector
返回后,您将无法利用这些知识做任何事情。
Thus, Seq.apply
返回它可能返回的最简单的东西,那就是List
.