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

时间:2010-12-31 09:17:45

标签: 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
    // ...
  }
}

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

  import MyString.stringToMyString

然后它有效。

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

3 个答案:

答案 0 :(得分:16)

  

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

真的。现在,方法camelize在类MyString上定义,实际上,在其对象伙伴中有一个隐式转换为MyString。但是,代码中没有任何内容告诉编译器MyString期望的目标类型。

相反,如果你写了这个:

val x = ("active_record": MyString).camelize

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

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

class Fraction(num: Int, denom: Int) {
    ...
    def +(b: Fraction) = ...
    ...
}

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

val x: Fraction = ...
val y = x + 5

现在,x确实有+方法,其预期类型Fraction。因此编译器会在这里查看对象Int内部FractionFraction的隐式转换(如果有的话,那么在对象Int内部,因为那是来源类型)。

答案 1 :(得分:13)

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

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

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

根据Pimp my library pattern见<{3}}:

  

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

object Implicits {
    implicit def listExtensions[A](xs : List[A]) = new ListExtensions(xs)
}
  

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

import Implicits._

答案 2 :(得分:0)

我在Scala编程书中尝试了Rational类示例,在其伴随对象中放入了一个隐式方法:

object Rational {
  implicit def intToRational(num: Int) = 
    new Rational(num)
}

但是代码

2 + new Rational(1, 2)

不起作用。为了进行转换,应用单个标识符规则,即,即使在伴随对象中定义了显式方法,也需要将显式方法导入范围。