Scala单例与伴生对象

Scala比Java更面向对象的一个方面是Scala没有静态成员。替代品是,Scala有单例对象:singleton object。app

当单例对象与某个类共享同一个名称时,他被称做是这个类的伴生对象:companion object。你必须在同一个源文件里定义类和它的伴生对象。类被称为是这个单例对象的伴生类:companion class。类和它的伴生对象能够互相访问其私有成员。函数

定义单例对象不是定义类型(在Scala的抽象层次上说)spa

类和单例对象间的一个差异是,单例对象不带参数,而类能够。由于你不能用new关键字实例化一个单例对象,你没机会传递给它参数。每一个单例对象都被做为由一个静态变量指向的虚构类:synthetic class的一个实例来实现,所以它们与Java静态类有着相同的初始化语法。Scala程序特别要指出的是,单例对象会在第一次被访问的时候初始化。scala

object AbstractTypeTest1 extends Application {
  def newIntSeqBuf(elem1: Int, elem2: Int): IntSeqBuffer =
    new IntSeqBuffer {
         type T = List[U]
         val element = List(elem1, elem2)
       }
  val buf = newIntSeqBuf(7, 8)
  println("length = " + buf.length)
  println("content = " + buf.element)
}

一个伴生对象的示例:code

import scala.collection.mutable.Map 
 
class ChecksumAccumulator { 
    private var sum = 0
            def add(b: Byte) { 
        sum += b 
    } 
 
    def checksum(): Int = ~(sum & 0xFF) + 1
}
 
object ChecksumAccumulator { 
    private val cache = Map[String, Int]() 
    def calculate(s: String): Int = 
    if (cache.contains(s)) 
        cache(s) 
    else { 
        val acc = new ChecksumAccumulator 
        for (c <- s) acc.add(c.toByte) 
        val cs = acc.checksum() 
        cache += (s -> cs) 
        cs 
    } 
}
 
object Summer { 
    def main(args: Array[String]) { 
        println(ChecksumAccumulator.calculate("Every value is an object."))
    }
}

输出为:orm

-248对象

可是伴生对象如何体现单例的呢?element

class Worker private{
  def work() = println("I am the only worker!")
}
 
object Worker{
  val worker = new Worker
  def GetWorkInstance() : Worker = {
    worker.work()
    worker
  }
}
 
object Job{
  def main(args: Array[String]) { 
        for (i <- 1 to 5) {
          Worker.GetWorkInstance();
        }
    }
}

单例模式就控制类实例的个数,经过伴生对象来访问类的实例就提供了控制实例个数的机会。一个简单示例:it

不与伴生类共享名称的单例对象被称为孤立对象:standalone object。最多见的就是程序入口:io

class Worker private声明了Worker的首构造函数是私有的,这样Worker的全部构造函数都不能直接被外部调用,由于全部从构造函数都会首先调用其余构造函数(能够是主构造函数,也能够是从构造函数),结果就是主构造函数是类的惟一入口点。

另外一方面,Worker.GetWorkInstance();有点相似静态函数调用,但在Scala中这是不对的。Scala会隐式地调用apply来建立一个伴生对象的实例。Scala是一个纯粹的面向对象语言,不容许有任何破坏对象模型的机制存在,好比类的静态变量、函数等。

相关文章
相关标签/搜索