Scala 中的 apply 和 update 方法

Scala 是構建在 JVM 上的靜態類型的腳本語言,而腳本語言總是會有些約定來增強靈活性。靈活性可以讓掌握了它的人如魚得水,也會讓初學者不知所措。比如說 Scala 爲配合 DSL 在方法調用時有這麼一條約定:

在明確了方法調用的接收者的情況下,若方法只有一個參數時,調用的時候就可以省略點及括號。如 “0 to 2”,實際完整調用是 “0.to(2)”。但 “println(2)” 不能寫成 “println 10“”,因爲未寫出方法調用的接收者 Console,所以可以寫成 “Console println 10”

到這裏就要講到 apply 和 update 方法相關的約定,描述的是直接在變量(對象)後直接加圓括號的代碼的情況下,那就是:

用括號傳遞給變量(對象)一個或多個參數時,Scala 會把它轉換成對 apply 方法的調用;與此相似的,當對帶有括號幷包括一到若干參數的進行賦值時,編譯器將使用對象的 update 方法對“括號裏的參數和等號右邊的值”執行調用。

對上面那段話的解釋可由下面幾個例子得到很好的理解

1. theArray(0), 取數組的第一個元素的操作會轉換成 theArray.apply(0) 操作,這也能解釋爲什麼 Scala 數組取值不用中括號括下標的方式,因爲它也是一次方法調用

2. anyObject("key1") 會被轉換成 anyObject.apply("key") 操作,這也會讓我們想到 Map 的取值操作,的確如此。我們可以作個例子:

[plain] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. classSomeClass {  
  2.     defapply(key:String):String ={  
  3.         println("apply method called, key is: " + key)  
  4.         "Hello World!"  
  5.     }  
  6. }  
  7.    
  8. valanyObject =new SomeClass  
  9. println(anyObject("key1"))  

執行後輸出結果是:

apply method called, key is: key1
Hello World!

說明是調用到了相應的 apply 方法的。

3. 我們在構造 Array 或  Map 時,會簡單的寫成

[plain] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. valnumNames =Array("zero","one","two")  

這裏也是調用的 apply 方法,我們看起來好像是作用在類 Array 上的,其實不然,而是作用在 Array 的伴生對象(object Array)上的,調用的是伴生對象 Array 的  apply 方法,即:

[plain] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. valnumNames =Array.apply("zero","one","two")  

上面的功效像是調用的 Array 類的 apply 工廠方法。同樣看個單例對象的例子,也解釋了伴生對象的 apply 方法的調用

[plain] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. objectEMail {  
  2.     defapply(user:String, domain:String):String ={  
  3.         println("apply method called")  
  4.         user + "@"+ domain  
  5.     }  
  6. }  
  7.    
  8. valemail =EMail("lyrebing","hotmail.com")  
  9. println(email)  

上面代碼執行後輸出結果是:

apply method called
[email protected]

有了前面 apply 方法的理解,下面對 update 方法的理解就很順暢了,比如:

[plain] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. greetStrings(0)="Hello"  

會轉換成調用

[plain] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. greetStrings.update(0,"Hello")  

來個複雜的 Demo,賦值時等號左邊帶兩個參數,並且賦值操作會產生返回值的情況(純粹用於演示)

[plain] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. classSomeClass {  
  2.     defupdate(arg1:Int, arg2:String, arg3:String):String ={  
  3.         println("update method called")  
  4.         arg1+ "|"+ arg2+ "|"+ arg3  
  5.     }  
  6. }  
  7.    
  8. valobj =new SomeClass  
  9. valresult =(obj(1,"key1")="Hello")  
  10. println(result)  

執行後輸出結果爲:

update method called
1|key1|Hello

在應用 apply 和 update 規則時,關鍵是轉換後的調用要找到相應的方法原型。再就是應用 update 時,等號右邊的值會作爲 update 方法的最後一個參數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章