当你用 Seq(1,2,3) 创建一个 Seq 对象时会发生什么? [英] What happens when you create a Seq object with Seq(1,2,3)?
问题描述
当你对表达式求值时到底发生了什么:Seq(1,2,3)
?
What exactly happens when you evaluate expression: Seq(1,2,3)
?
我是 Scala 的新手,现在对各种集合类型有点困惑.Seq 是一种特质,对吧?所以当你这样称呼它 Seq(1,2,3)
时,它一定是某种伴生对象吗?或不?它是某种扩展 Seq 的类吗?最重要的是返回值的类型是什么?是 Seq 吗?如果是,为什么不是明确的扩展类?
I am new to Scala and I am now a bit confused about various collection types. Seq is a trait, right? So when you call it like that Seq(1,2,3)
it must be some kind of a companion object? Or not? Is it some kind of a class that extends Seq? And most importantly what is the type of the returned value? Is it Seq and if yes, why is not explicitly the extension class instead?
也在 REPL 中我看到计算表达式的内容实际上是一个 List(1,2,3),但类型显然是 Seq[Int].为什么不是索引集合类型,如 Vector?这一切背后的逻辑是什么?
Also in REPL I see that the contents of the evaluated expression is actually a List(1,2,3), but the type is apparently Seq[Int]. Why is not an Indexed collection type, like Vector? What is the logic behind all that?
推荐答案
当你对表达式求值时到底发生了什么:
Seq(1,2,3)
?
在 Scala 中,foo(bar)
是 foo.apply(bar)
的语法糖,除非 this
也有一个名为 foo
,在这种情况下它是对隐式this
接收器的方法调用,即就像Java一样,它相当于this.foo(bar)代码>.
In Scala, foo(bar)
is syntactic sugar for foo.apply(bar)
, unless this
also has a method named foo
, in which case it is a method call on the implicit this
receiver, i.e. just like Java, it is then equivalent to this.foo(bar)
.
就像任何其他面向对象语言一样,方法调用的接收者单独决定如何处理该调用,因此在这种情况下,Seq
决定要做什么.
Just like any other OO language, the receiver of a method call alone decides what to do with that call, so in this case, Seq
decides what to do.
Seq 是一种特质,对吧?
Seq is a trait, right?
标准库中有两个Seq
:
所以当你这样称呼它时 Seq(1,2,3)
它一定是某种伴生对象吗?还是不行?
So when you call it like that
Seq(1,2,3)
it must be some kind of a companion object? Or not?
是的,它必须是一个对象,因为你只能在对象上调用方法.你不能在类型上调用方法,因此,当你看到一个方法调用时,它必须是一个对象.总是.因此,在这种情况下,Seq
不可能是 Seq
trait,它必须是 Seq
对象.
Yes, it must be an object, since you can only call methods on objects. You cannot call methods on types, therefore, when you see a method call, it must be an object. Always. So, in this case, Seq
cannot possibly be the Seq
trait, it must be the Seq
object.
请注意,它必须是某种伴生对象"是不正确的.从那段代码中您唯一可以看到的是 Seq
是一个对象.您无法从那段代码中知道它是否是伴随对象.为此,您必须查看源代码.在这种特殊情况下,事实证明它是,实际上是一个伴随对象,但你不能从你展示的代码中得出结论.
Note that "it must be some kind of a companion object" is not true. The only thing you can see from that piece of code is that Seq
is an object. You cannot know from that piece of code whether it is a companion object. For that, you would have to look at the source code. In this particular case, it turns out that it is, in fact, a companion object, but you cannot conclude that from the code you showed.
是某种扩展 Seq 的类吗?
Is it some kind of a class that extends Seq?
没有.它不可能是一个类,因为你只能在对象上调用方法,而类在 Scala 中不是对象.(这不像 Ruby 或 Smalltalk,其中类也是 Class
类的对象和实例.)它必须是一个对象.
No. It cannot possibly be a class, since you can only call methods on objects, and classes are not objects in Scala. (This is not like Ruby or Smalltalk, where classes are also objects and instances of the Class
class.) It must be an object.
最重要的是返回值的类型是什么?
And most importantly what is the type of the returned value?
最简单的方法是查看 Seq.apply 的文档:
The easiest way to find that out is to simply look at the documentation for Seq.apply:
A
:集合元素的类型elems
:创建的集合的元素- 返回一个包含元素 elems 的新集合
def apply[A](elems: A*): Seq[A]
Creates a collection with the specified elements.
A
: the type of the collection's elementselems
: the elements of the created collection- returns a new collection with elements elems
所以,如你所见,Seq.apply
的返回类型是 Seq
,或者更准确地说,Seq[A]
,其中 A
是一个类型变量,表示集合元素的类型.
So, as you can see, the return type of Seq.apply
is Seq
, or more precisely, Seq[A]
, where A
is a type variable denoting the type of the elements of the collection.
它是 Seq 吗?如果是,为什么不是明确的扩展类?
Is it Seq and if yes, why is not explicitly the extension class instead?
因为没有扩展类.
此外,Scala 中的标准设计模式是伴随对象的 apply
方法返回伴随类或特征的实例.打破这个惯例会很奇怪和令人惊讶.
Also, the standard design pattern in Scala is that the apply
method of a companion object returns an instance of the companion class or trait. It would be weird and surprising to break this convention.
也在 REPL 中我看到计算表达式的内容实际上是一个 List(1,2,3),但类型显然是 Seq[Int].
Also in REPL I see that the contents of the evaluated expression is actually a List(1,2,3), but the type is apparently Seq[Int].
静态类型是Seq[Int]
.这就是您需要知道的全部内容.这就是你可以知道的全部.
The static type is Seq[Int]
. That is all you need to know. That is all you can know.
现在,Seq
是一个trait
,并且traits不能被实例化,所以运行时类型将是Seq的一些子类代码>.但!您不能也不必关心它是什么特定的运行时类型.
Now, Seq
is a trait
, and traits cannot be instantiated, so the runtime type will be some subclass of Seq
. But! You cannot and must not care, what specific runtime type it is.
为什么不是索引集合类型,如 Vector?这一切背后的逻辑是什么?
Why is not an Indexed collection type, like Vector? What is the logic behind all that?
你怎么知道下次调用它时它不会返回Vector
?一点都不重要,因为静态类型是 Seq
,因此您只能在其上调用 Seq
方法,并且您只能依赖Seq
的契约,即 Seq
的后置条件、不变量等.即使你知道返回的是一个Vector
,你也无法利用这些知识做任何事情.
How do you know it is not going to return a Vector
the next time you call it? It wouldn't matter one bit, since the static type is Seq
and thus you are only allowed to call Seq
methods on it, and you are only allowed to rely on the contract of Seq
, i.e. Seq
's post-conditions, invariants, etc. anyway. Even if you knew it was a Vector
that is returned, you wouldn't be able to do anything with this knowledge.
因此,Seq.apply
返回它可能返回的最简单的东西,那就是一个 List
.
Thus, Seq.apply
returns the simplest thing it can possibly return, and that is a List
.
这篇关于当你用 Seq(1,2,3) 创建一个 Seq 对象时会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!