为什么不使用关键字“ new”创建新的Random

时间:2019-08-31 10:49:08

标签: scala singleton

在研究Scala时,我遇到了以下片段:

val r = Random

现在,根据我对Alvin Alexander的出色文章(How to create Scala object instances without using the “new” keyword (apply)的了解,您可以创建新的Scala对象实例,而无需使用new关键字,如下所示:

  • 为您的课程创建一个伴随对象,并定义一个apply方法 在具有所需构造函数签名的伴随对象中。
  • 将您的班级定义为“案例班级”。

但是,当我查看Random类(Scala 2.12.8)的源代码时,我发现它不是case类,并且伴随对象在其伴随对象中也没有apply方法。

有人可以向我解释为什么创建一个如上所述的随机数是有效的语法,即使它不满足Alvin Alexander帖子中所述的要求吗?

谢谢!

2 个答案:

答案 0 :(得分:3)

在这种情况下,Random是类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中的Foo.v已如何引用类Foo的实例单例值。因此,{p}中的r

val r = Random

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

val a = 11
val r = a

答案 1 :(得分:3)

简而言之:您不是在创建Random class新实例 ,而是在分配现有实例的 Random类,也恰好称为字段r的{​​{3}}。

听起来classobject都名为Random,这确实令人困惑,但是实际上不可能存在任何混淆,因为在Scala中,类型和术语存在于不同的“世界”及其名称永远不能混用。

请注意,实际上,classtraitobject的名称相同是很普遍的,原因如下:

  • 如果object与类或特征具有相同的名称,请
  • 在同一范围内object定义为与classtrait相同的名称,
  • object相同的编译单元中定义为classtrait,具有相同的名称,然后 < / li>

object被称为Random,并且在classtrait的内部具有companion module