Higher Order Functions 定義的是方法,而不是函數 函數可作為變數存在,可直接調用,也可作為值傳遞給其他函數 尾碼將普通方法變為函數: 根據上下文編譯器可以自動將方法轉換為函數,也可省略 尾碼 高階函數,接收函數的函數 參數類型推導 匿名函數傳遞給其他函數或方法時,如果一直到參數 ...
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
處理基礎類型,自動生成基礎類型對應包裝類的方法