理解 Scala 中的選項

Suraj P 2023年1月30日 2022年7月12日
  1. Scala 中的 Option 型別
  2. 在 Scala 中檢索 Option 的值
  3. Option 作為 Scala 中的容器
理解 Scala 中的選項

在本文中,我們將學習如何在 Scala 中使用可選資料元素。Scala 中的 Options 幫助我們編寫健壯的程式碼。

Scala 中的 Option 型別

Scala 中的 Option[T] 是一個容器,用於儲存零個或一個給定型別的值。使用 Scala 的 Option 管理可選值,我們可以確保兩件事:

  1. 型別安全:我們可以引數化可選值。
  2. 功能意識:option 型別提供了許多功能效能力,以確保在程式中產生更少的錯誤。

在 Scala 中,Option[T]Some[T]None[T] 物件表示。這裡的 scala.Option 是抽象和擴充套件的基類,使得 Scala 中的 Option 表現得像一個容器。

請記住,Option 類及其子類需要具體型別。它們可以是顯式的,也可以像下面的語法那樣推斷出來。

例子:

val obj1: Option[Int] = None
val obj2 = Some(100)

這裡 obj1obj2Option[Int] 的物件。一個常見的問題是如何檢查我們的 OptionSome 還是 None

為了解決這個問題,我們有以下功能。

  1. isEmpty:如果物件為 None,此方法返回 true
  2. nonEmpty:如果物件是 Some,此方法返回 true
  3. isDefined:如果物件是 Some,此方法返回 true

在 Scala 中檢索 Option 的值

我們可以使用 get 方法來檢索 Options 值。如果在 None 的物件上呼叫 get 方法,則丟擲 NoSuchElementException,也稱為 成功偏差

示例程式碼:

val obj1: Option[Int]= ...

val v1 = if (obj1.isDefined)
{
  obj1.get
}
else
{
  0
}

上面的程式碼也可以使用模式匹配來編寫。

示例程式碼:

val obj1: Option[Int]= ...

val v1 = obj1 match {
  case Some(temp) =>
    temp
  case None =>
    0
}

我們還有其他方法,例如 getOrElseorElse 來檢索值。

  1. getOrElse:如果物件是 Some,此方法檢索值;否則,它返回一個預設值。
  2. orElse:如果物件是 Some,此方法檢索值;否則返回一個 alternate 選項。

當未設定可選值時,getOrElse 方法非常有用,因為我們可以返回預設值。

語法:

val v1 = obj1.getOrElse(0)

Option 作為 Scala 中的容器

正如我們已經看到的那樣,Option 是 Scala 中另一個值的容器,就像我們遍歷 List 類似,我們可以遍歷 Option

讓我們看看這個容器的一些方法。Scala 中 Option.map 方法的語法:

final def map[Y](f: (X) => Y): Option[Y]

示例程式碼:

val obj1: Option[Int] = Some(100)
assert(obj1.map(_.toString).contains("100"))
assert(obj1.map(_ * 2.0).contains(200))

val obj2: Option[Int] = None
assert(obj2.map(_.toString).isEmpty)

在上面的示例中,我們使用 Option.map 方法將包含的值轉換為另一種型別。Option.map 方法也可用於影響程式的流控制

示例程式碼:

val obj1: Option[Int] = Some(10)
val obj2: Option[Int] = None

def mul(n: Int): Int = n * 2

assert(obj1.map(mul).contains(20))
assert(obj2.map(mul).isEmpty)

這裡我們建立了兩個 Option[Int] 物件,第一個物件的值為 10,第二個物件為空。然後我們定義了一個方法 mul 將輸入乘以 2

最後,我們使用 mul 方法對映 obj1obj2。對映 obj1 給我們 Some(20),對映 obj2 給我們 None

這裡要注意的一件事是,在第二次呼叫 obj2.map(mul) 中,根本沒有呼叫 mul 方法。我們也可以通過過濾進行流量控制。

我們有很多方法可以做到這一點:

  1. filter:如果 Options 值為 Some 並且提供的函式返回 true,則此方法返回 Option
  2. exists:如果設定了 Option 並且提供的函式返回 true,則此方法返回 true
  3. forall:行為與 exists 方法相同。

使用這些函式,我們可以非常簡潔地編寫程式碼。

讓我們舉一個例子,我們找到得分最高的球隊。

示例程式碼:

 def highScoringTeam(playerA: Player, playerB: Player, tournament: Tournament): Option[(Player, Int)] =
 { getTopScore(playerA, tournament).foldRight(getTopScore(playerB, tournament)) {
      case (playerAInfo, playerBInfo) => playerBInfo.filter {
        case (_, scoreB) => scoreB > playerAInfo._2
      }.orElse(Some(playerAInfo))
    }
  }

在上面的程式碼中,我們利用了 Options 可以用作集合。唯一的區別是 Option 最多可以有一個值。

Author: Suraj P
Suraj P avatar Suraj P avatar

A technophile and a Big Data developer by passion. Loves developing advance C++ and Java applications in free time works as SME at Chegg where I help students with there doubts and assignments in the field of Computer Science.

LinkedIn GitHub