Scala單例物件
阿新 • • 發佈:2019-01-25
宣告:作為自己學習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