Classes
- 一個源檔案可包含多個類,每個類默認都是 public
- 類欄位必須初始化,編譯后默認是 private,自動生成 public 的 getter/setter ;Person 示例
private欄位,生成 private 的 getter/setterval欄位,只生成 getterprivate[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.c與package a { package b { package c {}}}不同package a或package 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,scala和Predef- 后面匯入的可將前面的成員覆寫,避免沖突
- 匯入 scala 相關的包可省略
scala路徑
- 匯入包后可使用相對路徑訪問類等,如
Inheritance
fragile base class基類被繼承之后,修改基類可能會對子類造成無法預期的影響
-
繼承類,與 Java 一樣使用
extends關鍵字final類不能被繼承,final欄位、方法不能被覆寫
-
覆寫非抽象方法,必須使用
override關鍵字 -
抽象方法
- 無方法體的方法,可以省略
abstract關鍵字;子類覆寫時也可以省略override
- 無方法體的方法,可以省略
-
抽象欄位
- 無初始值的欄位,可省略
abstract關鍵字,子類覆寫式也可省略override
- 無初始值的欄位,可省略
-
呼叫父類方法,使用
super關鍵字 -
型別檢查和轉換,
isInstanceOf,asInstanceOf;獲取型別,classOf- 模式匹配通常是個更好的型別檢查方式
-
protected不同于 Java,受保護成員在包內不可見 -
輔助構造器不可直接呼叫超類構造器
- 可在定義類時直接在 extends 時呼叫超類構造器并傳遞引數
- 繼承 Java 類時主構造器必須呼叫超類的構造器
-
覆寫欄位
def只能覆寫defval只能覆寫 無引數的defvar只能覆寫 抽象的var
-
繼承層級

Any定義了asInstanceOf,isInstanceOf,判斷相等,hash值等方法AnyRef是除基礎型別外所有類的父類,等價于java.lang.Object- 提供方法
wait,notify/notifyAll,synchronized
- 提供方法
AnyVal不包含任何方法,只是個值型別的標記- 所有 Scala 類都實作了
ScalaObject這個標記介面,該介面無任何方法 Null的唯一實體null,可分配給參考型別,但不可分配給值型別(Int不可為null)Nothing無實體,在泛型構造時有用,Nil型別為List[Nothing]???方法宣告回傳型別為Nothing, 無回傳值,會拋出NotImplementedError,用于預留未實作的方法Unit代表空/void,型別唯一值為()- 如果方法引數型別為
Any或AnyRef, 當傳遞多個引數時,會被替換為tuple
-
equals和hashCode判斷物件相等- 可使用模式匹配實作
equals equals引數型別為Any而不是具體的型別##是hashCode的安全版本,遇到null會回傳 0 而不是拋出例外
- 可使用模式匹配實作
-
值類 Value Class
- 繼承
AnyVal - 主構造器只有一個引數 val,無構造體
- 無其他構造器和欄位
- 自動提供的
equals和hashCode比較實際值 - 用于隱式轉換
- 其他用途,如
class a(x: Int, y: Int)設計為class a(x: X, y: Y),定義值類X,Y避免混淆引數
- 其他用途,如
- 繼承
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/1979.html
標籤:Scala
上一篇:Scala Basis
