Scala Class etc. 2

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 關鍵字後接變量名或對應數據結構中使用變量名,那麼匹配項就賦值給該變量,變量名必須以小寫字母開頭
  • 使用 | 分隔同一匹配的多個可選項,此時不可以使用變量綁定元素
  • 類型匹配,代替 isInstanceOfasInstanceOf,直接進行類型轉換
    • 必須爲類型指定變量名,不然匹配的是實際的類型對象
    • 匹配在運行時發生,而 JVM 泛型會被擦除
      • 不能夠匹配具體的 Map 類型(可以使用 case Map[_, _],不可以使用 case Map[Int, Int]
      • Array 的類型不會被擦除
  • 解構 destructuring
    • 匹配數組html

      case Array(x, y) => s"$x $y"  // 匹配長度爲2的數組,並將分別綁定到 x, y
      case Array(0, rest @ _*) => rest.min // 可變參數
    • 匹配 Listjava

      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,默認提供 applyunapplytoStringequalshashCodecopy
      • 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 表達式是否編譯爲 ableswitchlookupswitch,若是被編譯成一系列條件表達式,則會拋出異常
    • @inline, @noinline 建議編譯器是否將方法替換爲行內調用
    • @elidable, 用於標註在生產代碼中可移除的方法
      • elidable 對象定義了不少級別常量可直接使用,未指定參數時默認是 SERVERE 即 1000(包含1000)
    • @specialized 處理基礎類型,自動生成基礎類型對應包裝類的方法
相關文章
相關標籤/搜索