1. 程式人生 > >Scala單例物件

Scala單例物件

宣告:作為自己學習Scala的筆記,只是為了以後複習Scala方便。

Singleton物件

Scala比Java更為面向物件的特點之一是Scala不能定義靜態成員,而是代之以定義單例物件(singleton object)。除了用object關鍵字替換了class關鍵字以外,單例物件的定義看上去與類定義一致。

// 私有構造方法
class Marker private(val color:String) {

    println("Creating " + this)

    override def toString(): String = "marker color "+ color

}

// 伴生物件,與類共享名字,可以訪問類的私有屬性和方法
object Marker{ private val markers: Map[String, Marker] = Map( "red" -> new Marker("red"), "blue" -> new Marker("blue"), "green" -> new Marker("green") ) def apply(color:String) = { if(markers.contains(color)) markers(color) else null } def
getMarker(color:String) = { if(markers.contains(color)) markers(color) else null } } object ObjectDemo { def main(args: Array[String]) { // 方法糖 apply //單例物件在第一次被訪問時才會被初始化。 println(Marker("red")) println() // 單例函式呼叫,省略了.(點)符號 println(Marker getMarker "blue"
) } }

輸出為:

Creating marker color red
Creating marker color blue
Creating marker color green
marker color red

marker color blue

上面例子中單例物件叫做Maker,與Maker類同名。當單例物件與某個類共享同一個名稱時,它就被稱為是這個類的伴生物件。類和它的伴生物件必須定義在一個原始檔中。類被稱為是這個單例物件的伴生類。類和它的伴生物件可以相互訪問其私有成員。

對於Java程式設計師來說,可以把單例物件當做是Java中可能會用到的靜態 方法工具類。也可以用類似的語法做方法呼叫:單例物件名,點,方法名。

類和單例物件間的差別是,單例物件不帶引數,而類可以。因為單例物件不是用new關鍵字例項化的,所以沒機會傳遞給它例項化引數。每個單例物件都被實現為虛構類的例項,並指向靜態的變數,因此它們與Java靜態類有著相同的初始化語義。

特別要指出的是,單例物件在第一次被訪問的時候才會被初始化。

將伴生物件作為工廠使用

我們通常將伴生物件作為工廠使用。

下面是一個簡單的例子,可以不需要使用’new’來建立一個例項了。

class Bar(foo: String)

object Bar {
    def apply(foo: String) = new Bar(foo)
}

建立物件是隻需要使用工廠方法,而不許要使用new來建立:
val bar = Bar(“foo”) 等價與
var bar = Bar.apply(“foo”)

獨立物件(standalone object)

不與伴生類共享名稱的單例物件被稱為獨立物件。它可以用在很多地方。例如,作為相關功能方法的工具類,或者定義Scala應用的入口點。

Demo

class ApplyDemo
{
    def apply() = "apply in class"
    def test
    {
        println("test")
    }
}

/**
  * 伴生物件,相當於類的靜態方法
  */
object ApplyDemo {

    def stat
    {
        println("static method")
    }

    def apply() = new ApplyDemo

    var count = 0

    def incc =
    {
        count += 1
    }
}

object ClassTest {
    def main(args: Array[String]): Unit = {
        ApplyDemo.stat

        //類名後面加括號,相當於呼叫伴生物件的apply方法
        val a = ApplyDemo()
        a.test

        //物件加括號相當於呼叫物件的apply方法
        println(a())

        val b = ApplyDemo.apply()
        b.test

        println(a.apply())

        for(i <- 0 until 10){
            ApplyDemo.incc
        }
        println(ApplyDemo.count)
    }
}

輸出為:

static method
test
apply in class
test
apply in class
10