Scala Class etc. 2
阿新 • • 發佈:2019-12-31
Higher-Order Functions
-
def
定義的是方法,而不是函式 - 函式可作為變數存在,可直接呼叫,也可作為值傳遞給其他函式
-
_
字尾將普通方法變為函式:ceil _
- 根據上下文編譯器可以自動將方法轉換為函式,也可省略
_
字尾
- 根據上下文編譯器可以自動將方法轉換為函式,也可省略
- 高階函式,接收函式的函式
- 引數型別推導
- 匿名函式傳遞給其他函式或方法時,如果一直到引數型別,則可省略匿名函式的引數型別,可自動推導型別
- 引數只有一個時可省略括號
- 當引數在右側只出現一次時,可使用
_
簡寫
- 當引數在右側只出現一次時,可使用
- 閉包 Closures,特定作用域
- SAM,single abstract method interface
- 對應 Java 中的函式式介面 (1.8)
- 可將 Scala 函式傳遞給 Java,只在函式字面量中起作用
- 柯里化 Currying
- 將接收兩個引數的函式變為接收第一個引數的函式,該函式返回一個消費第二個引數的函式
- 控制抽象 Control Abstractions
- Scala 只包含少量的流程控制語句,使用者可自定義控制語句
Pattern Matching and Case Classes
- 可對任何型別進行模式匹配,匹配順序從上至下
- 模式匹配代替
switch
,預設分支為case _
;可避免switch
語句中因缺少break
帶來的fall-through
問題 - 模式匹配也是表示式,可將其返回值直接賦值給變數
- 模式守衛 / guards,為匹配設定條件,任何
Boolean
條件都可作為模式守衛;case ... if ... => ...
-
case
關鍵字後接變數名或對應資料結構中使用變數名,那麼匹配項就賦值給該變數,變數名必須以小寫字母開頭 - 使用
|
分隔同一匹配的多個可選項,此時不可使用變數繫結元素 - 型別匹配,代替
isInstanceOf
和asInstanceOf
,直接進行型別轉換- 必須為型別指定變數名,否則匹配的是實際的型別物件
- 匹配在執行時發生,而 JVM 泛型會被擦除
- 不可以匹配具體的
Map
型別(可使用case Map[_,_]
,不可使用case Map[Int,Int]
-
Array
的型別不會被擦除
- 不可以匹配具體的
- 解構 destructuring
- 匹配陣列
case Array(x,y) => s"$x $y" // 匹配長度為2的陣列,並將分別繫結到 x,y
case Array(0,rest @ _*) => rest.min // 可變引數複製程式碼
- 匹配
List
case x :: y :: Nil => ... // 繫結引數
case head :: tail => ... // 解構 head,tail複製程式碼
- 匹配元組
case (0,_) => ... // 匹配第一個元素為0
case (x,y) => ... // 繫結引數複製程式碼
- 定義變數,注意一定要小寫開頭;其實等價於
match
模式匹配加上賦值操作-
val (x,y) = (1,2)
-
val Array(f,s,rest @ _*) = arr
-
- 用於
for
迴圈遍歷集合,匹配符合條件的元素
for ((k,v) <- System.getProperties()) println(s"$k $v")
// 匹配 value 為 "" 的項,其他的則被忽略
for ((k,"") <- System.getProperties()) println(k)
// if guard 過濾
for ((k,v) <- System.getProperties() if v == "") println(k)複製程式碼
- Case Class
- 用於模式匹配的特殊類
- 構造引數預設為
val
,預設提供apply
、unapply
、toString
、equals
、hashCode
、copy
-
copy
用於複製物件時,可使用命名引數來修改屬性
-
-
case class X
使用時case X() => ...
,需要括號 -
case object S
單例,使用時case S => ...
, 不要括號 -
::
也是 case class,配合中綴表示式,就是常見的匹配方式,case head :: tail
,實際呼叫::(head,tail)
- 可用於巢狀的結構;繫結變數、可變引數匹配類似
- 適用於固定結構的類,如
List
等
-
sealed
密封的- 被修飾的類,則其子類必須和該類在同一個檔案中定義
- 在編譯時即確定了所有匹配項的可能性
-
Option
也是使用 case class 來表示是否有值存在的- 子類
Some
封裝值,子類None
表示無值 - 相比使用
""
或null
更加安全 -
Map
進行get
操作返回的也是Option
,也可使用模式匹配來處理 -
getOrElse
嘗試獲取值,未獲取到則使用給定的值
- 子類
- Partial Function 偏函式
- 沒有對所有輸入進行定義的函式
-
apply
從模式匹配中計算函式值,isDefinedAt
判斷輸入是否匹配定義的模式 -
case
語句塊是偏函式 -
PartialFunction[A,B]
的例項,A
為輸入型別,B
為輸出型別- 可使用偏函式的
lift
方法,將偏函式變為常規函式,返回值為Option[B]
- 也可以通過
Function.unlift
將返回Option[B]
的函式變為偏函式
- 可使用偏函式的
-
Seq[A]
也是偏函式PartialFunction[Int,A]
-
Map[K,V]
也是偏函式PartialFunction[K,V]
-
catch
語句也是偏函式,可在catch
塊中使用模式匹配處理異常
註解
- Scala 中註解可影響程式碼編譯,如
@BeanProperty
會自動生成getter/setter
- 可用於 類、方法、欄位、變數、引數等
- 多個註解無順序
- 主構造器的註解,需要加括號
class Credential @Inject() (var username: String,var password: String)
- 表示式的註解,使用分號加註解的方式
(map.get(key): @unchecked) ...
- 型別引數的註解,
class Test[@specialized T]
- 實際型別的註解,放在型別之後,
def name: String @Localized
- 註解實現
- 註解必須繼承
Annotation
- 型別註解必須繼承
TypeAnnotation
- 元註解
@param
,@field
,@getter
,@setter
,@beanGetter
,@beanSetter
- 註解必須繼承
- 對應 Java 修飾符、標記介面
-
@volatile
對應volatile
關鍵字 -
@transient
對應transient
關鍵字 -
@strictfp
對應strictfp
關鍵字 -
@native
對應native
關鍵字 -
@cloneable
對應Cloneable
-
@remote
對應java.rmi.Remote
-
@SerialVersionUID
代替序列化欄位
-
- 使用
@throws(classOf[Exception])
來處理 Java 中的受檢異常 -
@varargs
處理可變引數-
@varargs def name(args: String*)
生成void name(String... args)
- 沒有
@varargs
則可變引數會被轉換成Seq[T]
-
- 優化
-
@tailrec
會嘗試優化尾遞迴呼叫,將其變為迴圈 -
@switch
編譯器會檢查match
表示式是否編譯為ableswitch` 或 `lookupswitch
,如果被編譯成一系列條件表示式,則會丟擲異常 -
@inline
,@noinline
建議編譯器是否將方法替換為行內呼叫 -
@elidable
,用於標註在生產程式碼中可移除的方法-
elidable
物件定義了很多級別常量可直接使用,未指定引數時預設是SERVERE
即 1000(包含1000)
-
-
@specialized
處理基礎型別,自動生成基礎型別對應包裝類的方法
-