前面提到Scala比Java更加面向?qū)ο蟠侥粒@是因?yàn)镾cala不允許類保護(hù)靜態(tài)元素(靜態(tài)變量或靜態(tài)方法)。在Scala中提供類似功能的是成為“Singleton(單例對象)“的對象丐重。在Scala中定義Singleton對象的方法除了使用object腔召,而非class關(guān)鍵字外和類定義非常類似,下面例子創(chuàng)建一個ChecksumAccumulator對象:
1
object
ChecksumAccumulator {
2
private
val
cache
=
Map [String, Int] ()
3
def
calculate(s
:
String)
:
Int
=
4
if
(cache.contains(s))
5
cache(s)
6
else
{
7
val
acc
=
new
ChecksumAccumulator
8
for
( c <- s)
9
acc.add(c.toByte)
10
val
cs
=
acc.checksum()
11
cache +
( s -> cs)
12
cs
13
}
14
}
這個對象和上一篇創(chuàng)建的類ChecksumAccumulator同名扮惦,這在Scala中把這個對象成為其同名的類的“伴侶”對象(Companion object)臀蛛。 如果你需要定義的類的companion對象,Scala要求你把這兩個定義放在同一個文件中崖蜜。類和其companion對象可以互相訪問對方的私有成員浊仆。如果你是Java成員,可以把Singleton對象看成以前Java定義靜態(tài)成員的地方豫领。你可以使用類似Java靜態(tài)方法的方式調(diào)用Singleton對象的方法抡柿,比如下面為這個例子完整的代碼:
1
import
scala.collection.mutable.Map
2
class
ChecksumAccumulator{
3
private
var
sum
=
0
4
def
add(b
:
Byte)
:
Unit
=
sum +
=
b
5
def
checksum()
:
Int
=
~ (sum &
0xFF
) +
1
6
}
7
8
object
ChecksumAccumulator {
9
private
val
cache
=
Map [String, Int] ()
10
def
calculate(s
:
String)
:
Int
=
11
if
(cache.contains(s))
12
cache(s)
13
else
{
14
val
acc
=
new
ChecksumAccumulator
15
for
( c <- s)
16
acc.add(c.toByte)
17
val
cs
=
acc.checksum()
18
cache +
( s -> cs)
19
cs
20
}
21
}
22
23
println ( ChecksumAccumulator.calculate(
"Welcome to Scala Chinese community"
))
Scala 的singleton對象不僅限于作為靜態(tài)對象的容器,它在Scala中也是頭等公民等恐,但僅僅定義Singleton對象本身不會創(chuàng)建一個新的類型洲劣,你不可以使用new再創(chuàng)建一個新的Singleton對象(這也是Singleton名字的由來),此外和類定義不同的是鼠锈,singleton對象不可以帶參數(shù)(類定義參數(shù)將在后面文章介紹)闪檬。
回過頭來看看我們的第一個例子”Hello World“。
1
object
HelloWorld {
2
def
main(args
:
Array[String]) {
3
println(
"Hello, world!"
)
4
}
5
}
這是一個最簡單的Scala程序,HelloWorld 是一個Singleton對象购笆,它包含一個main方法(可以支持命令行參數(shù))粗悯,和Java類似,Scala中任何Singleto對象同欠,如果包含main方法,都可以作為應(yīng)用的入口點(diǎn)。在這里要說明一點(diǎn)的是盖呼,在Scala中不要求public類定義和其文件名同名鲤屡,不過使用和public類和文件同名還是有它的優(yōu)點(diǎn)的闪萄,你可以根據(jù)個人喜好決定是否遵循Java文件命名風(fēng)格。最后提一下Scala的trait功能,Scala的trait 和Java 的Interface相比,可以有方法的實(shí)現(xiàn)(這點(diǎn)有點(diǎn)像抽象類,但如果是抽象類膛锭,就不會允許繼承多個抽象類)。Scala的Trait支持類和Singleton對象和多個Trait混合(使用來自這些Trait中的方法蚊荣,而不時不違反單一繼承的原則)初狰。Scala為Singleton對象的main定義了一個App trait類型,因此上面的例子可以簡化為:
1
object
HelloWorld
extends
App{
2
println(
"Hello, world!"
)
3
}
這段代碼就不能作為腳本運(yùn)行互例,Scala的腳本要求代碼最后以表達(dá)式結(jié)束奢入。因此運(yùn)行這段代碼,需要先編譯這段代碼:scalac Helloworld.scala
編譯好之后媳叨,運(yùn)行該應(yīng)用
scala HelloWord
注意: Scala提供了一個快速編譯代碼的輔助命令fsc (fast scala compliler) 腥光,使用這個命令,只在第一次使用fsc時啟動JVM,之后fsc在后臺運(yùn)行糊秆,這樣就避免每次使用scalac時都要載入相關(guān)庫文件武福,從而提高編譯速度。