萬物皆對象:介紹Scala對象
本文源自Michel Schinz和Philipp Haller所寫的A Scala Tutorial for Java programmers,由Bearice成中文。之前一篇為Scala簡單做了一下入門,這一篇描述Scala對象。在Scala中,一切都是對象,所以數(shù)字和函數(shù)都是Scala對象。
51CTO編輯推薦:Scala編程語言專題
4 Scala:萬物皆對象
Scala作為一個純面向?qū)ο蟮恼Z言,于是在Scala中萬物皆對象,包括數(shù)字和函數(shù)。在這方面,Scala于Java存在很大不同:Java區(qū)分原生類型(比如boolean和int)和引用類型,并且不能把函數(shù)當(dāng)初變量操縱。
4.1 數(shù)字和對象
由于數(shù)字本身就是對象,所以他們也有方法。事實上我們平時使用的算數(shù)表達(dá)式(如下例)
1 + 2 * 3 / x
是由方法調(diào)用組成的。它等效于下面的表達(dá)式,我們在上一節(jié)見過這個描述。
(1).+(((2).*(3))./(x))
這也意味著 +,-,*,/ 在Scala中也是有效的名稱。
在第二個表達(dá)式中的這些括號是必須的,因為Scala的分詞器使用最長規(guī)則來進(jìn)行分詞。所以他會把下面的表達(dá)式:
1.+(2)
理解成表達(dá)項 1. ,+,和2的組合。這樣的組合結(jié)果是由于1.是一個有效的表達(dá)項并且比表達(dá)項1要長,表達(dá)項1.會被當(dāng)作1.0 ,使得它成為一個double而不是int。而下面的表達(dá)式阻止了分析器錯誤的理解
(1).+(2)
4.2 函數(shù)與對象
函數(shù)在Scala語言里面也是一個對象,也許這對于Java程序員來說這比較令人驚訝。于是吧函數(shù)作為參數(shù)進(jìn)行傳遞、把它們存貯在變量中、或者當(dāng)作另一個函數(shù)的返回值都是可能的。吧函數(shù)當(dāng)成值進(jìn)行操作是函數(shù)型編程語言的基石。
為了解釋為什么吧函數(shù)當(dāng)作值進(jìn)行操作是十分有用的,我們來考慮一個計時器函數(shù)。這個函數(shù)的目的是每隔一段時間就執(zhí)行某些操作。那么如何吧我們要做的操作傳入計時器呢?于是我們想吧他當(dāng)作一個函數(shù)。這種目前的函數(shù)對于經(jīng)常進(jìn)行用戶界面編程的程序員來說是最熟悉的:注冊一個回調(diào)函數(shù)以便在事件發(fā)生后得到通知。
在下面的程序中,計時器函數(shù)被叫做oncePerSceond,它接受一個回調(diào)函數(shù)作為參數(shù)。這種函數(shù)的類型被寫作 () => Unit ,他們不接受任何參數(shù)也沒有任何返回(Unit關(guān)鍵字類似于C/C++中的void)。程序的主函數(shù)調(diào)用計時器并傳遞一個打印某個句子的函數(shù)作為回調(diào)。換句話說,這個程序永無止境的每秒打印一個“time flies like an arrow”。
object Timer {
def oncePerSecond(callback: () => Unit) {
while (true) { callback(); Thread sleep 1000 }
}
def timeFlies() {
println("time flies like an arrow...")
}
def main(args: Array[String]) {
oncePerSecond(timeFlies)
}
}
注意,我們輸出字符串時使用了一個預(yù)定義的函數(shù)println而不是使用System.out中的那個。
4.2.1 匿名函數(shù)
我們可以吧這個程序改的更加易于理解。首先我們發(fā)現(xiàn)定義函數(shù)timeFlies的***目的就是當(dāng)作傳給oncePerSecond的參數(shù)。這么看來給這種只用一次的函數(shù)命名似乎沒有什么太大的必要,事實上我們可以在用到這個函數(shù)的時候再定義它。這些可以通過匿名函數(shù)在Scala中實現(xiàn),匿名函數(shù)顧名思義就是沒有名字的函數(shù)。我們在新版的程序中將會使用一個匿名函數(shù)來代替原來的timeFlise函數(shù),程序看起來像這樣:
object TimerAnonymous {
def oncePerSecond(callback: () => Unit) {
while (true) { callback(); Thread sleep 1000 }
}
def main(args: Array[String]) {
oncePerSecond(() =>
println("time flies like an arrow..."))
}
}
本例中的匿名函數(shù)使用了一個箭頭(=>)吧他的參數(shù)列表和代碼分開。在這里參數(shù)列表是空的,所以我們在右箭頭的左邊寫上了一對空括號。函數(shù)體內(nèi)容與上面的timeFlise是相同的。
了解了Scala對象的特點,接下來一篇將會介紹Scala類。
【相關(guān)閱讀】