【《快學Scala》筆記】函數
一、Scala中的類是公有可見性的,且多個類能夠包含在同一個源文件中;this
1 class Counter{ 2 private var value = 0 //類成員變量必須初始化,不然報錯 3 4 def increment(){ //類中的方法默認是公有可見性 5 value += 1 6 } 7 8 def current() = value //對於類中的「取值方法」,在定義時可省略掉括號,直接 def current = value 9 }
Scala類的使用:spa
Scala的類在未提供構造器時,也會提供默認構造器;且在調用無參構造器或無參方法時可省略掉方法後的括號。scala
二、Scala類的每一個字段都有getter和setter方法,私有字段的getter和setter默認是私有的,公有字段的getter和setter方法默認是公有的。code
其中對於類中的屬性value,Scala類默認生成的getter方法名爲 value,默認生成的setter方法名爲 value_= 。使用時,咱們能夠從新定義獲取或設置屬性的方法。對象
例如,blog
1 class Clock{ 2 var hour = 0 3 var minute = 0 4 var second = 0 5 6 def getTime():String={ 7 return hour+":"+minute+":"+second 8 } 9 }
對於Clock類中的屬性,如 hour,其對應的getter方法爲 hour ,其對應的setter方法名爲 hour_= 繼承
【注:能夠從新定義獲取Scala類中屬性的方法,可是最好不要與屬性默認對應的getter/setter方法重名,不然會報錯。】
三、對於Scala類中的val屬性,只有默認的getter方法;對於private屬性,其默認getter、setter都是private的。於是,對於不想提供setter方法的變量能夠設置爲val,對於不想提供getter、setter方法的變量能夠設置爲private。
四、注意,Scala類中,定義無參函數時,若函數聲明時省略了函數名後的括號(因爲無參數,能夠省略),調用時,必須參數無括號的形式,經過帶括號形式調用會報錯。如,
1 class Counter{ 2 var value = 0 3 4 def current = value 5 }
類Counter定義中,對於方法current,因爲不接受參數,因此定義時省略了方法名current後的括號。此時,對於Counter的實例counter,調用current方法時,必須採用counter.current(無括號形式)。
五、對於Scala類中定義的字段,在Scala中實際爲私有字段。(還有待進一步理解和驗證)
1 class Counter{ 2 var value = 0 3 val sum = 0 4 private var cnt = 1 5 6 //.... 7 }
在Counter類中,Scala在爲Counter生成面向JVM的類時,對於value字段,會生成對應的私有字段value和公有的getter、setter方法;對於sum字段,會生成私有的final字段和公有的getter方法;對於cnt字段,會生成私有字段cnt和私有的getter、setter方法(貌似這個private聲明只是影響的Scala根據屬性生成的對應getter、setter的可見性)。
六、構造器
Scala的類能夠有一個主構造器和多個輔助構造器。每一個輔助構造器的名稱爲this,每個輔助構造器都必須以調用已經定義的輔助構造器或主構造器開始定義。
若是一個類沒有顯示定義主構造器,則有一個默認的無參主構造器。
如定義一個Student類,
1 class Student(val name:String, var age:Int = 0, address:String = "", private var school:String = ""){ 2 var grade:Int = if( age>7 ) age-7 else 0 3 4 println(" I'm in main constructor. ") 5 6 def info() = " name is "+name+", age is "+age+", address is "+address 7 }
對於Scala類,主構造器的參數放置在類名後,由括號括起來。且對於主構造器中var、val、private 等標註的參數,都會成爲類的對應字段,並生成對應的默認getter、setter方法。如Student類中的name、age、school等。對於主構造器中的未用var、val標註的參數,若是在類的任何一個方法用用到該參數,該參數將會轉換爲類的字段,不然不會,如Student類的address屬性。
因爲在Student類中的info方法中用到了參數address,因此Student共有name、age、address、school、grade等5個屬性,且Scala根據對應屬性的特色生成了默認的getter和setter方法。
對於主構造器的參數,也能夠提供參數默認值。經過爲主構造器提供默認值可減小輔助構造器的個數。
主構造器的函數體,是類中除了方法定義之外的其餘語句,如在Student類的主構造器中,包含grade屬性的初始化和prinln這兩行語句。
Stuent類的使用。
輔助構造器經過this來定義,且必須首先調用主構造器或者其餘已經定義的輔助構造器。
1 class Person(val name:String){ 2 var age = 0 3 var sex:Char = 'f' 4 5 println("main constructor...") 6 7 def this(name:String, age:Int){ 8 this(name) //調用主構造器 9 this.age = age //使用this關鍵字 10 11 println(" auxiliary constructor1 ") 12 } 13 14 def this(name:String, age:Int, sex:Char){ 15 this(name, age) 16 17 this.sex = sex 18 19 println(" auxiliary constructor2 ") 20 } 21 }
【注:輔助構造器的參數前不能添加val、var標誌,不然會報錯。】
1 class Person private(val name:String){ 2 var age:Int = 1 3 4 def this(name: String, age:Int){ 5 this(name) 6 this.age = age 7 } 8 9 }
私有構造器經過在類名後用private關鍵字標註主構造器參數來標明。此時,能夠經過輔助構造器來建立該類的對象。
七、嵌套類
1 class Family(val h_name:String, val w_name:String){ 2 class Husband(var name:String){ 3 println(" I'm a husband ") 4 } 5 6 class Wife(var name:String){ 7 println(" I'm a Wife ") 8 } 9 10 var husband = new Husband(h_name) 11 var wife = new Wife(w_name) 12 13 def info(){ 14 println( "husband: "+husband.name+", wife:"+wife.name ) 15 } 16 }
在Scala中,你幾乎能夠在任何語法結構中嵌套任何語法結構,如在函數中定義函數,在類中定義類。
一、Scala中沒有靜態方法和靜態字段,可是能夠用object語法來實現相似的功能。對象定義了某個類的單個實例。
Scala的object中能夠用來實現相似的功能,用來存放工具函數或常量等。如,
1 object Sequence{ 2 private var next_num = 0 3 val threshold = 100 4 5 def getSequence() = { 6 next_num += 1 7 next_num 8 } 9 }
使用object中的常量或方法,經過object名直接調用,對象構造器在對象第一次被使用時調用(若是某對象一直未被使用,那麼其構造器也不會被調用)。
object的構造器不接受參數傳遞。
二、伴生對象
能夠將在Java類中定義的靜態常量、方法等放置到Scala的類的伴生對象中。伴生對象與類同名,且必須放置在同一源文件中。類能夠訪問伴生對象私有特性,可是必須經過 伴生對象.屬性名 或 伴生對象.方法 調用。
伴生對象是類的一個特殊實例。
1 class Counter{ 2 def getTotalCounter()= Counter.getCount 3 } 4 5 object Counter{ 6 private var cnt = 0 7 8 private def getCount()= cnt 9 }
如在類Counter訪問其伴生對象的石油方法getCount,必須經過 Counter.getCount() 的方式調用。
三、對象能夠繼承或擴展多個特質
1 abstract class Person(var name:String, var age:Int){ 2 def info():Unit 3 } 4 5 object XiaoMing extends Person("XiaoMing", 5){ 6 def info(){ 7 println(" name is "+name+", age is "+age) 8 } 9 }
四、apply方法
當遇到 object(參數1, 參數2,....,參數n)的形式的調用時,apply方法便會被調用。
五、main方法——Scala程序的入口
main方法定義在object中,形式以下:
1 object HelloWorld{ 2 def main(args: Array[String]){ 3 println("Hello World!") 4 } 5 }
能夠經過scalac 源文件名,而後經過 scala 類名 來執行主程序。
六、還能夠經過擴展特質App來運行指定代碼
1 object HelloWorld2 extends App{ 2 println(" A 'Hello world' from HelloWorld2 ") 3 }
經過擴展App特質的方式執行程序時,將要執行的程序放到了object的主構造器中。
七、枚舉
Scala並無定義枚舉類型,可是能夠經過定義擴展Enumeration的對象,並用Value方法初始化枚舉類中的全部可選值,提供枚舉。
1 object TrafficeLight extends Enumeration{ 2 val Red, Yellow, Green = Value 3 4 }
上述實例中的val Red, Yellow, Green = Value語句,至關於
1 val Red = Value 2 val Yellow = Value 3 val Green = Value
用Value方法初始化枚舉類變量時,Value方法會返回內部類的新實例,且該內部類也叫Value。另外,在調用Value方法時,也可傳入ID、名稱兩參數。若是未指定ID,默認從零開始,後面參數的ID是前一參數ID值加1。若是未指定名稱,默認與屬性字段同名。
1 object TrafficLight extends Enumeration{ 2 val Red = Value(1, "Stop") 3 val Yellow = Value("Wait") //能夠單獨傳名稱 4 val Green = Value(4) //能夠單獨傳ID 5 }
上例中,Yellow屬性就僅定義了名稱,Green僅定義ID。
參數在不指定名稱時,默認參數的Value爲字段名。
【注:枚舉類型的值是, 對象名.Value ,如上例中的枚舉類型是 TrafficLight.Value。】
八、經過id方法獲取枚舉類型值的ID
九、經過values方法獲取全部枚舉值的集合
十、經過ID來獲取對應的枚舉對象