隐式转换,是否需要导入?

Xen*_*fex 14 scala implicit-conversion

我写

object MyString {
  implicit def stringToMyString(s: String) = new MyString(s)    
}

class MyString(str: String) {
  def camelize = str.split("_").map(_.capitalize).mkString

  override def toString = str
}


object Parse {
  def main(args: Array[String]) {
    val x = "active_record".camelize
    // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

在我的程序中.这会导致编译错误.我插入后

  import MyString.stringToMyString
Run Code Online (Sandbox Code Playgroud)

然后它工作.

从Odersky的Scala编程中我得到了源的伴随对象中的隐式转换,或者不需要导入预期的目标类型.

Dan*_*ral 16

不需要导入源或预期目标类型的伴随对象中的隐式转换.

真的够了.现在,该方法camelize是在类上定义的MyString,实际上,MyString在其对象伴随内部存在隐式转换.但是,代码中没有任何内容告诉编译器它MyString预期的目标类型.

相反,如果你写了这个:

val x = ("active_record": MyString).camelize
Run Code Online (Sandbox Code Playgroud)

然后它会工作,因为编译器会知道你期望 "active_record"成为a MyString,使它查找对象内部的隐式转换MyString.

这可能看起来有点限制,但实际上它可以在很多地方使用.比方说,你有:

class Fraction(num: Int, denom: Int) {
    ...
    def +(b: Fraction) = ...
    ...
}
Run Code Online (Sandbox Code Playgroud)

然后你有一个像这样的代码:

val x: Fraction = ...
val y = x + 5
Run Code Online (Sandbox Code Playgroud)

现在,x确实有一个+方法,其预期类型Fraction.因此,编译器会看,这里,为的隐式转换从IntFraction物体内部Fraction(和对象里面Int,如果有一个,因为这是源类型).


Eug*_*ota 13

在这种情况下,您需要导入,因为编译器不知道从哪里拉出camelize方法.如果类型是明确的,它将编译而不导入:

object Parse {
  def foo(s: MyString) = s.camelize

  def main(args: Array[String]) {
    val x = foo("active_record")
    println(x.toString)
  }
}
Run Code Online (Sandbox Code Playgroud)

根据Martin的文章,参见皮条客我的图书馆模式:

请注意,无法将defs置于顶层,因此您无法使用全局范围定义隐式转换.解决方案是将def放在一个对象中,然后导入它,即

object Implicits {
    implicit def listExtensions[A](xs : List[A]) = new ListExtensions(xs)
}
Run Code Online (Sandbox Code Playgroud)

然后在每个源文件的顶部,以及其他导入:

import Implicits._
Run Code Online (Sandbox Code Playgroud)