4.5 独立对象和伴生对象

上面看到的MarkerFactory是个独立对象的例子。它并未自动关联到任何一个类上,即便它管理了Marker的实例。

Scala也可以创建一个关联到类上的单例。这样的单例同类共享相同的名字,它称为伴生对象,对应的类就称为伴生类。在上一个例子里,我们想控制Marker实例的创建。在Scala里,类和伴生对象之间没有界限——它们可以互相访问彼此的private字段和private方法。此外,在Scala里,还可以把构造函数标记为private。下面用伴生对象重写了Marker

ScalaForTheJavaEyes/Marker.scala

  1. class Marker private (val color: String) {
  2. println("Creating " + this)
  3. override def toString() : String = "marker color " + color
  4. }
  5. object Marker {
  6. private val markers = Map(
  7. "red" -> new Marker("red"),
  8. "blue" -> new Marker("blue"),
  9. "green" -> new Marker("green")
  10. )
  11. def getMarker(color: String) =
  12. if (markers.contains(color)) markers(color) else null
  13. }

下面的样例代码用到了修改过的类:

ScalaForTheJavaEyes/UseMarker.scala

  1. println(Marker getMarker "blue")
  2. println(Marker getMarker "blue")
  3. println(Marker getMarker "red")
  4. println(Marker getMarker "red")

输出如下:

  1. Creating marker color red
  2. Creating marker color blue
  3. Creating marker color green
  4. marker color blue
  5. marker color blue
  6. marker color red
  7. marker color red

Marker的构造函数标记为private,但是伴生对象依然可以访问它。所以可以在伴生对象中创建Marker的实例。但是如果在Marker类或伴生对象之外创建Marker实例,就会得到错误信息。

每个类都可以有伴生对象,它们跟伴生类写在同一个文件中。伴生对象在Scala中很常见,它们提供了在类一级进行操作的便捷方法。同时,它们还可以作为Scala缺少静态成员的变通措施,下面马上就会讲到。