Scala Class etc.

Classes

  • 一個源文件可包含多個類,每一個類默認都是 public
  • 類字段必須初始化,編譯後默認是 private,自動生成 public 的 getter/setter ;Person 示例
    • private 字段,生成 private 的 getter/setter
    • val 字段,只生成 getter
    • private[this] 字段,不生成 getter/setter
    • 自定義 getter/setter,foo 和 foo_=
  • 類方法默認都是 public
  • 方法調用規約:訪問器調用可省略括號,修改器調用加上括號
  • 爲字段加上 @bean.BeanProperty 註解可生成符合 JavaBean 規範的 get/set 方法(加上默認的兩個方法,共四個方法)
  • 構造器:1 個主構造器,任意個輔構造器
    • 所有都叫 this,只是參數不一樣
    • 輔構造器必須調用主構造器或以前定義的輔構造器
    • 主構造器與類定義密不可分,參數直接定義在類名後
    • 主構造器會當即執行類定義中的全部語句
    • 主構造器中的參數被方法使用到,則對應的參數等價於 private[this] val 字段
  • 內部類
    • 路徑依賴,不一樣於 Java 內部類,同一類 A 的不一樣實例(a1, a2)構建的內部類 Inner,其類型是不一樣的,a1.Inner != a2.Inner
    • 解決路徑依賴
      • 類型投射,Outer#Inner
      • 將內部類放到伴生對象 object 中
    • self => 自身類型,區分調用的內部類和外部類的字段、方法等

Objects

  • 用於單例及工具類方法
    • object 構造器只在第一次被調用時執行
  • 可繼承一個 class 或多個 trait
    • 可用於全局默認對象
  • 不可提供構造器參數
  • 伴生對象
    • 與類名稱一致
    • 類與伴生對象可互相訪問私有資源,但區分做用域,如 Accounts.newUniqueNumber() 而不是 newUniqueNumber()
    • 類與伴生對象必須在同一個源文件中
  • 伴生對象中的 apply 方法
    • 調用方式 Object(arg1, ..., argN), 返回伴生類的實例,如 Array(1,2,3)
    • 省略 new 關鍵字,在嵌套表達式中很方便
  • 應用對象
    • extends App
    • 不須要 main 方法直接執行構造器內的代碼
  • scala 默認無枚舉類型
    • 使用 Enumeration 幫助類實現
    • 枚舉類型爲 Enumeration.Value(ID, name) 內部類, ID 依次累加, 默認 0 開始;name 默認是字段名

Traits

  • 替代 Java 中的接口
  • 能夠有抽象的和具體的方法
    • trait 中未實現的方法默認是抽象的 (abstract)
  • 類能夠實現多個 trait,從最後一個開始調用
    • 使用 extends 關鍵字實現
    • 覆蓋抽象方法時不須要 override 關鍵字
    • 有多個 trait 則對其餘的 trait 使用 with 關鍵字
  • 全部的 Java 接口均可以被當作 trait 使用
  • 對象也能夠添加多個 trait,從最後一個開始調用
  • 多個 trait 的狀況下,super.someMethod 會根據從右向左的順序調用下一個 trait 的方法
    • 具體調用依賴於使用時的順序,相比傳統的繼承更靈活
    • 在多個 mix-in 的狀況下,若是父trait存在抽象方法,則子trait需使用 abstract override 關鍵字,不然 super.someMethod 沒法編譯
  • 有初始值的字段/具體字段,都會被添加到子類中
  • 無初始值的字段/抽象字段,在非抽象子類中,須要進行初始化
  • trait 也有構造器
    • 不能夠有構造參數,且只有一個構造器
    • 由定義體中的初始化字段和其餘語句構成
    • 構造順序:父類 > 各trait從左向右,有父 trait 的先構造,共享的父 trait 只構造一次 > 子類
    • 考慮到構造順序,若是子類中使用抽象字段,則可以使用提早定義(early definition,會在構造器以前執行)的語法講改字段初始化
      • 提早定義語句塊中只能使用字段定義語句,不可以使用其餘語句
  • trait 可繼承類,混入該 trait 的類都是被繼承類的子類,子類若是有繼承其餘的類也必須是被繼承類的子類
  • 與自身類型(self type)比較
    • trait 不繼承類,直接在 body 內定義 this: Type =>,則混入的類必須是該 Type 類型的/子類型的
    • 也可以使用結構類型(structural type),this: { def log(msg: String) } => ,則混入的類必須包含結構類型中定義的方法
  • trait 最終會翻譯成類和接口

Packages and Imports

  • package 包名和文件路徑並不必定對應
  • java.lang, scala, Predef 始終默認會導入
  • 與 Java 不一樣,包路徑並非絕對的,如 collection.mutable 實際是 scala.collection.mutable
  • package a.b.cpackage a { package b { package c {}}} 不一樣
    • package apackage b 中定義的資源可在帶括號的包聲明中訪問,但 package a.b.c 沒法訪問
  • 包對象
    • package 因爲 JVM 的限制不能直接聲明函數或變量
    • 不一樣於 package, package object 可定義工具函數或常量
  • 可見性控制,經過 private[package.name] 限制資源的可見性
  • import
    • 導入包後可以使用相對路徑訪問類等,如 collection.mutable
    • 導入全部資源 import collection.mutable._
    • 可在任意位置進行導入操做
    • selector
      • 選擇性的導入一部分紅員,import java.awt.{Color, Font}
      • 爲導入成員取別名:import java.util.{HashMap => JavaMap}
      • 隱藏成員: import java.util.{HashMap => _, _} // 避免產生混淆
    • 隱式導入,默認導入三個 java.lang, scalaPredef
      • 後面導入的可將前面的成員覆蓋,避免衝突
      • 導入 scala 相關的包可省略 scala 路徑

Inheritance

fragile base class 基類被繼承以後,修改基類可能會對子類形成沒法預期的影響java

  • 繼承類,與 Java 同樣使用 extends 關鍵字
    • final 類不能被繼承, final 字段、方法不能被覆蓋
  • 覆蓋非抽象方法,必須使用 override 關鍵字
  • 抽象方法
    • 無方法體的方法,能夠省略 abstract 關鍵字;子類覆蓋時也能夠省略 override
  • 抽象字段
    • 無初始值的字段,可省略 abstract 關鍵字,子類覆蓋式也可省略 override
  • 調用父類方法,使用 super 關鍵字
  • 類型檢查和轉換, isInstanceOf, asInstanceOf;獲取類型, classOf
    • 模式匹配一般是個更好的類型檢查方式
  • protected 不一樣於 Java,受保護成員在包內不可見
  • 輔助構造器不可直接調用超類構造器
    • 可在定義類時直接在 extends 時調用超類構造器並傳遞參數
    • 繼承 Java 類時主構造器必須調用超類的構造器
  • 覆蓋字段
    • def 只能覆蓋 def
    • val 只能覆蓋 無參數的 def
    • var 只能覆蓋 抽象的 var
  • 繼承層級git

    file
    • Any 定義了 asInstanceOf, isInstanceOf,判斷相等,hash值等方法
    • AnyRef 是除基礎類型外全部類的父類,等價於 java.lang.Object
      • 提供方法 wait, notify/notifyAllsynchronized
    • AnyVal 不包含任何方法,只是個值類型的標記
    • 全部 Scala 類都實現了 ScalaObject 這個標記接口,該接口無任何方法
    • Null 的惟一實例 null,可分配給引用類型,但不可分配給值類型(Int 不可爲 null)
    • Nothing 無實例,在泛型構造時有用,Nil 類型爲 List[Nothing]
    • ??? 方法聲明返回類型爲 Nothing, 無返回值,會拋出 NotImplementedError,用於預留未實現的方法
    • Unit 表明空/void,類型惟一值爲 ()
    • 若是方法參數類型爲 AnyAnyRef, 當傳遞多個參數時,會被替換爲 tuple
  • equalshashCode 判斷對象相等
    • 可以使用模式匹配實現 equals
    • equals 參數類型爲 Any 而不是具體的類型
    • ##hashCode 的安全版本,遇到 null 會返回 0 而不是拋出異常
  • 值類 Value Class
    • 繼承 AnyVal
    • 主構造器只有一個參數 val,無構造體
    • 無其餘構造器和字段
    • 自動提供的 equalshashCode 比較實際值
    • 用於隱式轉換
      • 其餘用途,如 class a(x: Int, y: Int) 設計爲 class a(x: X, y: Y) ,定義值類 X, Y 避免混淆參數
相關文章
相關標籤/搜索