为什么我可以在没有关键字 "new" 的情况下创建新的 Random

Why can I create new Random without the keyword "new"

在我对 Scala 的学习中,我 运行 进入以下片段:

val r = Random

现在根据我对 Alvin Alexander 的优秀 post 的理解(How to create Scala object instances without using the “new” keyword (apply) 你可以创建一个新的 Scala 对象实例而不使用 new 关键字,如下所示:

但是,当我查看 Random class (Scala 2.12.8) 的源代码时,我发现这不是一个案例 class,伴随对象也没有 apply 方法在它的伴生对象中。

有人可以向我解释为什么像上面 post 那样创建 Random 是有效的语法,即使它不符合 Alvin Alexander post 中描述的要求吗?

谢谢!

在此上下文中 Random 是 class Random

的单例实例
object Random extends Random

哪里

class Random(val self: java.util.Random) extends ... {
  ...
  def this() = this(new java.util.Random())
  ...
}

因此它已经是一个值。例如考虑以下

class Foo(val v: Int)
object Foo extends Foo(42)
Foo.v

输出

res0: Int = 42

请注意 Foo.v 中的 Foo 如何已经引用 class Foo 的实例单例值。因此 r

val r = Random

只是引用现有的单例值。它类似于

val a = 11
val r = a

简单地说:您不是创建Random class, you are assigning the existing instance of the Random class which also happens to be called Random字段r新实例 .

同时存在一个名为 class 和一个名为 Randomobject 听起来可能令人困惑,但实际上不可能有任何混淆,因为在 Scala 中,类型和术语存在于不同的 "worlds" 并且他们的名字永远不能混用。

请注意,classtraitobject 同名实际上很常见,原因如下:

  • 如果 object 与 class 或特征同名,
  • objectclasstrait 同名 相同范围 中定义和
  • objectclasstrait 同名的 相同编译单元 中定义,然后

objectclasstrait 的内部称为 companion module and has privileged access