Scala 導覽

上下文參數,又稱隱含參數

語言

方法可以有上下文參數,也稱為隱含參數,或更簡潔地稱為隱含。從關鍵字 using(或 Scala 2 中的 implicit)開始的參數清單標記上下文參數。除非呼叫網站明確提供這些參數的引數,否則 Scala 會尋找正確類型的隱含可用 given(或 Scala 2 中的 implicit)值。如果可以找到適當的值,它會自動傳遞它們。

最好先使用一個小範例來說明。我們定義一個介面 Comparator[A],它可以比較類型 A 的元素,並提供兩個實作,分別適用於 IntString。然後我們定義一個方法 max[A](x: A, y: A),它會傳回兩個引數中較大的那個。由於 xy 是泛型類型,一般來說我們不知道如何比較它們,但我們可以要求一個適當的比較器。由於通常任何給定類型 A 都有一個正規比較器,我們可以將它們宣告為given,或隱含可用。

trait Comparator[A] {
  def compare(x: A, y: A): Int
}

object Comparator {
  implicit object IntComparator extends Comparator[Int] {
    def compare(x: Int, y: Int): Int = Integer.compare(x, y)
  }

  implicit object StringComparator extends Comparator[String] {
    def compare(x: String, y: String): Int = x.compareTo(y)
  }
}

def max[A](x: A, y: A)(implicit comparator: Comparator[A]): A =
  if (comparator.compare(x, y) >= 0) x
  else y

println(max(10, 6))             // 10
println(max("hello", "world"))  // world
// does not compile:
println(max(false, true))
//         ^
//     error: could not find implicit value for parameter comparator: Comparator[Boolean]

comparator 參數會自動填入 Comparator.IntComparator,適用於 max(10, 6),以及 Comparator.StringComparator,適用於 max("hello", "world")。由於找不到隱含的 Comparator[Boolean],因此呼叫 max(false, true) 會編譯失敗。

trait Comparator[A]:
  def compare(x: A, y: A): Int

object Comparator:
  given Comparator[Int] with
    def compare(x: Int, y: Int): Int = Integer.compare(x, y)

  given Comparator[String] with
    def compare(x: String, y: String): Int = x.compareTo(y)
end Comparator

def max[A](x: A, y: A)(using comparator: Comparator[A]): A =
  if comparator.compare(x, y) >= 0 then x
  else y

println(max(10, 6))             // 10
println(max("hello", "world"))  // world
// does not compile:
println(max(false, true))
-- Error: ----------------------------------------------------------------------
1 |println(max(false, true))
  |                        ^
  |no given instance of type Comparator[Boolean] was found for parameter comparator of method max

對於 max(10, 6)comparator 參數會自動填入 given Comparator[Int],而對於 max("hello", "world"),則會填入 given Comparator[String]。由於找不到 given Comparator[Boolean],因此 max(false, true) 呼叫無法編譯。

Scala 會在兩個地方尋找可用的 given 值

  • Scala 會先尋找 given 定義,並在 max 的呼叫位置直接存取使用參數(無前綴)。
  • 然後尋找在與隱含候選類型相關聯的伴隨物件中標記為 given/implicit 的成員(例如:object Comparator 對於候選類型 Comparator[Int])。

可以在 常見問題 中找到 Scala 尋找隱含值位置的更詳細指南。

此頁面的貢獻者