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是一個純粹的面嚮對象語言,不容許有任何破壞對象模型的機制存在,好比類的靜態變量、函數等。

相關文章
相關標籤/搜索