變形提取器

提取器行為可用於從其輸入中派生任意值。這在你希望能夠在轉換成功的情況下對轉換結果執行操作的情況下非常有用。

以 Windows 環境中可用的各種使用者名稱格式為例 :

object UserPrincipalName {
  def unapply(str: String): Option[(String, String)] = str.split('@') match {
    case Array(u, d) if u.length > 0 && d.length > 0 => Some((u, d))
    case _ => None
  }        
}

object DownLevelLogonName {
  def unapply(str: String): Option[(String, String)] = str.split('\\') match {
    case Array(d, u) if u.length > 0 && d.length > 0 => Some((d, u))
    case _ => None
  }
}

def getDomain(str: String): Option[String] = str match {
  case UserPrincipalName(_, domain) => Some(domain)
  case DownLevelLogonName(domain, _) => Some(domain)
  case _ => None
}

事實上,通過擴充套件它可以匹配的型別,可以建立一個展示這兩種行為的提取器:

object UserPrincipalName {
  def unapply(obj: Any): Option[(String, String)] = obj match {
    case upn: UserPrincipalName => Some((upn.username, upn.domain))
    case str: String => str.split('@') match {
      case Array(u, d) if u.length > 0 && d.length > 0 => Some((u, d))
      case _ => None
    }
    case _ => None
  }        
}

一般來說,提取器只是一種方便的 Option 模式重構,適用於名稱如 tryParse 的方法:

UserPrincipalName.unapply("user@domain") match {
  case Some((u, d)) => ???
  case None => ???
}