在 GitHub 上编辑此页面

隐式转换

隐式转换由 scala.Conversion 类的给定实例定义。此类在包 scala 中定义如下

abstract class Conversion[-T, +U] extends (T => U):
  def apply (x: T): U

例如,这里是从 StringToken 的隐式转换

given Conversion[String, Token] with
  def apply(str: String): Token = new KeyWord(str)

使用别名可以更简洁地表示为

given Conversion[String, Token] = new KeyWord(_)

编译器在以下三种情况下自动应用隐式转换

  1. 如果表达式 e 的类型为 T,并且 T 不符合表达式的预期类型 S
  2. 在选择 e.m 中,e 的类型为 T,但 T 未定义任何成员 m
  3. 在应用 e.m(args) 中,e 的类型为 T,如果 T 定义了一些名为 m 的成员,但这些成员都不能应用于参数 args

在第一种情况下,编译器会查找给定的 scala.Conversion 实例,该实例将类型为 T 的参数映射到类型 S。在第二种和第三种情况下,它会查找给定的 scala.Conversion 实例,该实例将类型为 T 的参数映射到定义成员 m 的类型,如果存在,则可以将该成员应用于 args。如果找到这样的实例 C,则表达式 e 将替换为 C.apply(e)

示例

  1. Predef 包含将基本数字类型映射到 java.lang.Number 子类的“自动装箱”转换。例如,从 Intjava.lang.Integer 的转换可以定义如下

    given int2Integer: Conversion[Int, java.lang.Integer] =
      java.lang.Integer.valueOf(_)
    
  2. “磁铁”模式有时用于表示方法的许多变体。与其定义方法的重载版本,还可以让方法采用一个或多个专门定义的“磁铁”类型的参数,各种参数类型都可以转换为该类型。示例

    object Completions:
    
      // The argument "magnet" type
      enum CompletionArg:
        case Error(s: String)
        case Response(f: Future[HttpResponse])
        case Status(code: Future[StatusCode])
    
      object CompletionArg:
    
        // conversions defining the possible arguments to pass to `complete`
        // these always come with CompletionArg
        // They can be invoked explicitly, e.g.
        //
        //   CompletionArg.fromStatusCode(statusCode)
    
        given fromString    : Conversion[String, CompletionArg]               = Error(_)
        given fromFuture    : Conversion[Future[HttpResponse], CompletionArg] = Response(_)
        given fromStatusCode: Conversion[Future[StatusCode], CompletionArg]   = Status(_)
      end CompletionArg
      import CompletionArg.*
    
      def complete[T](arg: CompletionArg) = arg match
        case Error(s) => ...
        case Response(f) => ...
        case Status(code) => ...
    
    end Completions
    

此设置比简单的 complete 重载复杂,但如果无法使用普通重载(如上例所示,因为我们不能有两个采用 Future[...] 参数的重载方法),或者如果普通重载会导致变体的组合爆炸,它仍然很有用。

本文中