Scala 伴生对象不是单例

Scala companion objects are not singleton

我有以下两个类。

class A (name: String) {
}

object A {
}

根据单例的定义,我们只能有一个该类型的对象。但是,我可以使用以下代码创建两个类型为 A 的不同对象。

object B {
   def main(args: Array[String]): Unit = {
     val a = new A("Vinod")
     println(a)

     val b = new A("XYZ")
     println(b)
  }
}

谁能解释一下,我的理解哪里不对?

可以将伴随对象视为 class 的静态 space。如果你想让 A 成为一个单例,你可以把它变成一个对象而不是 class

new A 指的是 class A(不是单例),而不是 object A。您可以轻松检查它:如果删除 class Anew A 行将不再编译。

另请注意 object 并非 必然 单例:它们可以嵌套在 类 或特征中,在这种情况下有一个用于外部类型的每个实例。

伴生对象不是伴生对象的实例 class。他们甚至不是同一种类型。

class A
object A {
  var state = 0
  def update() :Unit = state = state + 1
}

val abc :A = new A   //instance of class A
val xyz :A.type = A  //2nd reference to object A

// both reference the same singleton object
xyz.update()  //res0: Unit = ()
A.state       //res1: Int = 1
abc.state     //Error: value state is not a member of A$A2521.this.A

一个object本身一个单例。它有自己的 class 并且在运行时不存在相同 class 的其他实例。

但是,您在这里描述的模式是不同的:object A 不是 class A 的实例,除非您这样做使用 object A extends A。您可以通过将 class A 设为 sealed class 使其成为 class A 的唯一实例,但这在几乎所有情况下都是不必要的.

如果您真的想要单例模式,请删除 class 并仅使用 object A,它的所有成员都将是 "static" 意义上的 Java。

注意object A的实际类型可以参考A.type,默认情况下与类型A完全无关if class A 存在。同样,A.type 可以 A 的子类型,如果你明确地这样做的话。