Classes
- 一個(gè)源文件可包含多個(gè)類,每個(gè)類默認(rèn)都是 public
- 類字段必須初始化,編譯后默認(rèn)是 private,自動(dòng)生成 public 的 getter/setter ;Person 示例
-
private字段,生成 private 的 getter/setter -
val字段,只生成 getter -
private[this]字段,不生成 getter/setter - 自定義 getter/setter,foo 和 foo_=
-
- 類方法默認(rèn)都是 public
- 方法調(diào)用規(guī)約:訪問(wèn)器調(diào)用可省略括號(hào),修改器調(diào)用加上括號(hào)
- 為字段加上
@bean.BeanProperty注解可生成符合 JavaBean 規(guī)范的 get/set 方法(加上默認(rèn)的兩個(gè)方法,共四個(gè)方法) - 構(gòu)造器:1 個(gè)主構(gòu)造器,任意個(gè)輔構(gòu)造器
- 全部都叫
this,只是參數(shù)不同 - 輔構(gòu)造器必須調(diào)用主構(gòu)造器或之前定義的輔構(gòu)造器
- 主構(gòu)造器與類定義密不可分,參數(shù)直接定義在類名后
- 主構(gòu)造器會(huì)立即執(zhí)行類定義中的所有語(yǔ)句
- 主構(gòu)造器中的參數(shù)被方法使用到,則對(duì)應(yīng)的參數(shù)等價(jià)于
private[this] val字段
- 全部都叫
- 內(nèi)部類
- 路徑依賴,不同于 Java 內(nèi)部類,同一類 A 的不同實(shí)例(a1, a2)構(gòu)建的內(nèi)部類 Inner,其類型是不同的,a1.Inner != a2.Inner
- 解決路徑依賴
- 類型投射,Outer#Inner
- 將內(nèi)部類放到伴生對(duì)象 object 中
-
self =>自身類型,區(qū)分調(diào)用的內(nèi)部類和外部類的字段、方法等
Objects
- 用于單例及工具類方法
- object 構(gòu)造器只在第一次被調(diào)用時(shí)執(zhí)行
- 可繼承一個(gè)
class或多個(gè)trait- 可用于全局默認(rèn)對(duì)象
- 不可提供構(gòu)造器參數(shù)
- 伴生對(duì)象
- 與類名稱一致
- 類與伴生對(duì)象可互相訪問(wèn)私有資源,但區(qū)分作用域,如
Accounts.newUniqueNumber()而不是newUniqueNumber() - 類與伴生對(duì)象必須在同一個(gè)源文件中
- 伴生對(duì)象中的
apply方法- 調(diào)用方式
Object(arg1, ..., argN), 返回伴生類的實(shí)例,如Array(1,2,3) - 省略
new關(guān)鍵字,在嵌套表達(dá)式中很方便
- 調(diào)用方式
- 應(yīng)用對(duì)象
extends App- 不需要 main 方法直接執(zhí)行構(gòu)造器內(nèi)的代碼
- scala 默認(rèn)無(wú)枚舉類型
- 使用
Enumeration幫助類實(shí)現(xiàn) - 枚舉類型為
Enumeration.Value(ID, name)內(nèi)部類, ID 依次累加, 默認(rèn) 0 開(kāi)始;name 默認(rèn)是字段名
- 使用
Traits
- 替代 Java 中的接口
- 可以有抽象的和具體的方法
- 在
trait中未實(shí)現(xiàn)的方法默認(rèn)是抽象的 (abstract)
- 在
- 類可以實(shí)現(xiàn)多個(gè)
trait,從最后一個(gè)開(kāi)始調(diào)用- 使用
extends關(guān)鍵字實(shí)現(xiàn) - 覆蓋抽象方法時(shí)不需要
override關(guān)鍵字 - 有多個(gè)
trait則對(duì)其他的trait使用with關(guān)鍵字
- 使用
- 所有的 Java 接口都可以被當(dāng)做
trait使用 - 對(duì)象也可以添加多個(gè)
trait,從最后一個(gè)開(kāi)始調(diào)用 - 多個(gè)
trait的情況下,super.someMethod會(huì)根據(jù)從右向左的順序調(diào)用下一個(gè)trait的方法- 具體調(diào)用依賴于使用時(shí)的順序,相比傳統(tǒng)的繼承更靈活
- 在多個(gè) mix-in 的情況下,如果父
trait存在抽象方法,則子trait需使用abstract override關(guān)鍵字,否則super.someMethod無(wú)法編譯
- 有初始值的字段/具體字段,都會(huì)被添加到子類中
- 無(wú)初始值的字段/抽象字段,在非抽象子類中,需要進(jìn)行初始化
-
trait也有構(gòu)造器- 不可以有構(gòu)造參數(shù),且只有一個(gè)構(gòu)造器
- 由定義體中的初始化字段和其他語(yǔ)句構(gòu)成
- 構(gòu)造順序:父類 > 各
trait從左向右,有父trait的先構(gòu)造,共享的父trait只構(gòu)造一次 > 子類 - 考慮到構(gòu)造順序,如果子類中使用抽象字段,則可使用提前定義(early definition,會(huì)在構(gòu)造器之前執(zhí)行)的語(yǔ)法講改字段初始化
- 提前定義語(yǔ)句塊中只能使用字段定義語(yǔ)句,不可使用其他語(yǔ)句
-
trait可繼承類,混入該trait的類都是被繼承類的子類,子類如果有繼承其他的類也必須是被繼承類的子類 - 與自身類型(self type)比較
-
trait不繼承類,直接在 body 內(nèi)定義this: Type =>,則混入的類必須是該 Type 類型的/子類型的 - 也可使用結(jié)構(gòu)類型(structural type),
this: { def log(msg: String) } =>,則混入的類必須包含結(jié)構(gòu)類型中定義的方法
-
-
trait最終會(huì)翻譯成類和接口
Packages and Imports
-
package包名和文件路徑并不一定對(duì)應(yīng) -
java.lang,scala,Predef始終默認(rèn)會(huì)導(dǎo)入 - 與 Java 不同,包路徑并不是絕對(duì)的,如
collection.mutable實(shí)際是scala.collection.mutable -
package a.b.c與package a { package b { package c {}}}不同-
package a或package b中定義的資源可在帶括號(hào)的包聲明中訪問(wèn),但package a.b.c無(wú)法訪問(wèn)
-
- 包對(duì)象
- package 由于 JVM 的限制不能直接聲明函數(shù)或變量
- 不同于 package, package object 可定義工具函數(shù)或常量
- 可見(jiàn)性控制,通過(guò)
private[package.name]限制資源的可見(jiàn)性 -
import- 導(dǎo)入包后可使用相對(duì)路徑訪問(wèn)類等,如
collection.mutable - 導(dǎo)入所有資源
import collection.mutable._ - 可在任意位置進(jìn)行導(dǎo)入操作
-
selector- 選擇性的導(dǎo)入一部分成員,
import java.awt.{Color, Font} - 為導(dǎo)入成員取別名:
import java.util.{HashMap => JavaMap} - 隱藏成員:
import java.util.{HashMap => _, _}// 避免產(chǎn)生混淆
- 選擇性的導(dǎo)入一部分成員,
- 隱式導(dǎo)入,默認(rèn)導(dǎo)入三個(gè)
java.lang,scala和Predef- 后面導(dǎo)入的可將前面的成員覆蓋,避免沖突
- 導(dǎo)入 scala 相關(guān)的包可省略
scala路徑
- 導(dǎo)入包后可使用相對(duì)路徑訪問(wèn)類等,如
Inheritance
fragile base class基類被繼承之后,修改基類可能會(huì)對(duì)子類造成無(wú)法預(yù)期的影響
-
繼承類,與 Java 一樣使用
extends關(guān)鍵字-
final類不能被繼承,final字段、方法不能被覆蓋
-
覆蓋非抽象方法,必須使用
override關(guān)鍵字-
抽象方法
- 無(wú)方法體的方法,可以省略
abstract關(guān)鍵字;子類覆蓋時(shí)也可以省略override
- 無(wú)方法體的方法,可以省略
-
抽象字段
- 無(wú)初始值的字段,可省略
abstract關(guān)鍵字,子類覆蓋式也可省略override
- 無(wú)初始值的字段,可省略
調(diào)用父類方法,使用
super關(guān)鍵字-
類型檢查和轉(zhuǎn)換,
isInstanceOf,asInstanceOf;獲取類型,classOf- 模式匹配通常是個(gè)更好的類型檢查方式
protected不同于 Java,受保護(hù)成員在包內(nèi)不可見(jiàn)-
輔助構(gòu)造器不可直接調(diào)用超類構(gòu)造器
- 可在定義類時(shí)直接在 extends 時(shí)調(diào)用超類構(gòu)造器并傳遞參數(shù)
- 繼承 Java 類時(shí)主構(gòu)造器必須調(diào)用超類的構(gòu)造器
-
覆蓋字段
-
def只能覆蓋def -
val只能覆蓋 無(wú)參數(shù)的def -
var只能覆蓋 抽象的var
-
-
繼承層級(jí)
file-
Any定義了asInstanceOf,isInstanceOf,判斷相等,hash值等方法 -
AnyRef是除基礎(chǔ)類型外所有類的父類,等價(jià)于java.lang.Object- 提供方法
wait,notify/notifyAll,synchronized
- 提供方法
-
AnyVal不包含任何方法,只是個(gè)值類型的標(biāo)記 - 所有 Scala 類都實(shí)現(xiàn)了
ScalaObject這個(gè)標(biāo)記接口,該接口無(wú)任何方法 -
Null的唯一實(shí)例null,可分配給引用類型,但不可分配給值類型(Int不可為null) -
Nothing無(wú)實(shí)例,在泛型構(gòu)造時(shí)有用,Nil類型為List[Nothing] -
???方法聲明返回類型為Nothing, 無(wú)返回值,會(huì)拋出NotImplementedError,用于預(yù)留未實(shí)現(xiàn)的方法 -
Unit代表空/void,類型唯一值為() - 如果方法參數(shù)類型為
Any或AnyRef, 當(dāng)傳遞多個(gè)參數(shù)時(shí),會(huì)被替換為tuple
-
-
equals和hashCode判斷對(duì)象相等- 可使用模式匹配實(shí)現(xiàn)
equals -
equals參數(shù)類型為Any而不是具體的類型 -
##是hashCode的安全版本,遇到null會(huì)返回 0 而不是拋出異常
- 可使用模式匹配實(shí)現(xiàn)
-
值類 Value Class
- 繼承
AnyVal - 主構(gòu)造器只有一個(gè)參數(shù) val,無(wú)構(gòu)造體
- 無(wú)其他構(gòu)造器和字段
- 自動(dòng)提供的
equals和hashCode比較實(shí)際值 - 用于隱式轉(zhuǎn)換
- 其他用途,如
class a(x: Int, y: Int)設(shè)計(jì)為class a(x: X, y: Y),定義值類X,Y避免混淆參數(shù)
- 其他用途,如
- 繼承
