Scala 的類與 Java 的類具備很是多的類似性,示例以下:java
// 1. 在 scala 中,類不須要用 public 聲明,全部的類都具備公共的可見性 class Person { // 2. 聲明私有變量,用 var 修飾的變量默認擁有 getter/setter 屬性 private var age = 0 // 3.若是聲明的變量不須要進行初始賦值,此時 Scala 就沒法進行類型推斷,因此須要顯式指明類型 private var name: String = _ // 4. 定義方法,應指明傳參類型。返回值類型不是必須的,Scala 能夠自動推斷出來,可是爲了方便調用者,建議指明 def growUp(step: Int): Unit = { age += step } // 5.對於改值器方法 (即改變對象狀態的方法),即便不須要傳入參數,也建議在聲明中包含 () def growUpFix(): Unit = { age += 10 } // 6.對於取值器方法 (即不會改變對象狀態的方法),沒必要在聲明中包含 () def currentAge: Int = { age } /** * 7.不建議使用 return 關鍵字,默認方法中最後一行代碼的計算結果爲返回值 * 若是方法很簡短,甚至能夠寫在同一行中 */ def getName: String = name } // 伴生對象 object Person { def main(args: Array[String]): Unit = { // 8.建立類的實例 val counter = new Person() // 9.用 var 修飾的變量默認擁有 getter/setter 屬性,能夠直接對其進行賦值 counter.age = 12 counter.growUp(8) counter.growUpFix() // 10.用 var 修飾的變量默認擁有 getter/setter 屬性,能夠直接對其進行取值,輸出: 30 println(counter.age) // 輸出: 30 println(counter.currentAge) // 輸出: null println(counter.getName) } }
Scala 中成員變量的可見性默認都是 public,若是想要保證其不被外部干擾,能夠聲明爲 private,並經過 getter 和 setter 方法進行訪問。git
getter 和 setter 屬性與聲明變量時使用的關鍵字有關:github
須要特別說明的是:假設變量名爲 age,則其對應的 get 和 set 的方法名分別叫作 age
和 age_=
。shell
class Person { private val name = "heibaiying" private var age = 12 private[this] var birthday = "2019-08-08" // birthday 只能被內部方法所訪問 def getBirthday: String = birthday } object Person { def main(args: Array[String]): Unit = { val person = new Person person.age = 30 println(person.name) println(person.age) println(person.getBirthday) } }
解釋說明:編程
示例代碼中
person.age=30
在執行時內部實際是調用了方法person.age_=(30)
,而person.age
內部執行時實際是調用了person.age()
方法。想要證實這一點,能夠對代碼進行反編譯。同時爲了說明成員變量可見性的問題,咱們對下面這段代碼進行反編譯:ideclass Person { var name = "" private var age = "" }依次執行下面編譯命令:函數式編程
> scalac Person.scala > javap -private Person編譯結果以下,從編譯結果能夠看到實際的 get 和 set 的方法名 (由於 JVM 不容許在方法名中出現=,因此它被翻譯成$eq),同時也驗證了成員變量默認的可見性爲 public。函數
Compiled from "Person.scala" public class Person { private java.lang.String name; private java.lang.String age; public java.lang.String name(); public void name_$eq(java.lang.String); private java.lang.String age(); private void age_$eq(java.lang.String); public Person(); }
在上面的例子中能夠看到咱們是使用 .
來對成員變量進行訪問的,若是想要額外生成和 Java 中同樣的 getXXX 和 setXXX 方法,則須要使用@BeanProperty 進行註解。工具
class Person { @BeanProperty var name = "" } object Person { def main(args: Array[String]): Unit = { val person = new Person person.setName("heibaiying") println(person.getName) } }
和 Java 不一樣的是,Scala 類的主構造器直接寫在類名後面,但注意如下兩點:測試
static{}
class Person(val name: String, val age: Int) { println("功能相似於 Java 的靜態代碼塊 static{}") def getDetail: String = { //name="heibai" 沒法經過編譯 name + ":" + age } } object Person { def main(args: Array[String]): Unit = { val person = new Person("heibaiying", 20) println(person.getDetail) } } 輸出: 功能相似於 Java 的靜態代碼塊 static{} heibaiying:20
輔助構造器有兩點硬性要求:
class Person(val name: String, val age: Int) { private var birthday = "" // 1.輔助構造器的名稱必須爲 this def this(name: String, age: Int, birthday: String) { // 2.每一個輔助構造器必須以主構造器或其餘的輔助構造器的調用開始 this(name, age) this.birthday = birthday } // 3.重寫 toString 方法 override def toString: String = name + ":" + age + ":" + birthday } object Person { def main(args: Array[String]): Unit = { println(new Person("heibaiying", 20, "2019-02-21")) } }
在 Scala 中,方法傳參默認是 val 類型,即不可變,這意味着你在方法體內部不能改變傳入的參數。這和 Scala 的設計理念有關,Scala 遵循函數式編程理念,強調方法不該該有反作用。
class Person() { def low(word: String): String = { word="word" // 編譯沒法經過 word.toLowerCase } }
Scala 中的 object(對象) 主要有如下幾個做用:
這裏咱們建立一個對象 Utils
,代碼以下:
object Utils { /* *1. 至關於 Java 中的靜態代碼塊 static,會在對象初始化時候被執行 * 這種方式實現的單例模式是餓漢式單例,即不管你的單例對象是否被用到, * 都在一開始被初始化完成 */ val person = new Person // 2. 全局固定常量 等價於 Java 的 public static final val CONSTANT = "固定常量" // 3. 全局靜態方法 def low(word: String): String = { word.toLowerCase } }
其中 Person 類代碼以下:
class Person() { println("Person 默認構造器被調用") }
新建測試類:
// 1.ScalaApp 對象擴展自 trait App object ScalaApp extends App { // 2.驗證單例 println(Utils.person == Utils.person) // 3.獲取全局常量 println(Utils.CONSTANT) // 4.調用工具類 println(Utils.low("ABCDEFG")) } // 輸出以下: Person 默認構造器被調用 true 固定常量 abcdefg
在 Java 中,你一般會用到既有實例方法又有靜態方法的類,在 Scala 中,能夠經過類和與類同名的伴生對象來實現。類和伴生對象必須存在與同一個文件中。
class Person() { private val name = "HEIBAIYING" def getName: String = { // 調用伴生對象的方法和屬性 Person.toLow(Person.PREFIX + name) } } // 伴生對象 object Person { val PREFIX = "prefix-" def toLow(word: String): String = { word.toLowerCase } def main(args: Array[String]): Unit = { val person = new Person // 輸出 prefix-heibaiying println(person.getName) } }
Scala 中沒有直接提供枚舉類,須要經過擴展 Enumeration
,並調用其中的 Value 方法對全部枚舉值進行初始化來實現。
object Color extends Enumeration { // 1.類型別名,建議聲明,在 import 時有用 type Color = Value // 2.調用 Value 方法 val GREEN = Value // 3.只傳入 id val RED = Value(3) // 4.只傳入值 val BULE = Value("blue") // 5.傳入 id 和值 val YELLOW = Value(5, "yellow") // 6. 不傳入 id 時,id 爲上一個聲明變量的 id+1,值默認和變量名相同 val PINK = Value }
使用枚舉類:
// 1.使用類型別名導入枚舉類 import com.heibaiying.Color.Color object ScalaApp extends App { // 2.使用枚舉類型,這種狀況下須要導入枚舉類 def printColor(color: Color): Unit = { println(color.toString) } // 3.判斷傳入值和枚舉值是否相等 println(Color.YELLOW.toString == "yellow") // 4.遍歷枚舉類和值 for (c <- Color.values) println(c.id + ":" + c.toString) } //輸出 true 0:GREEN 3:RED 4:blue 5:yellow 6:PINK
更多大數據系列文章能夠參見 GitHub 開源項目: 大數據入門指南