【问题标题】:Implicit conversion, import required or not?隐式转换,是否需要导入?
【发布时间】:2010-12-31 09:17:45
【问题描述】:

我写

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 中的编程中,我得到了源或预期目标类型的伴随对象中的隐式转换不需要导入。

【问题讨论】:

    标签: scala implicit-conversion


    【解决方案1】:

    随播广告中的隐式转换 来源或预期的对象 目标类型不需要是 进口的。

    确实如此。现在,方法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。因此,编译器会在此处查找对象 Fraction 内从 IntFraction 的隐式转换(如果有的话,在对象 Int 内,因为那是源类型)。

    【讨论】:

      【解决方案2】:

      在这种情况下,您需要导入,因为编译器不知道您从哪里提取了 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,基于Martin's article

      请注意,不能将 defs 放在顶层,因此您不能定义具有全局范围的隐式转换。解决方法是将def放在一个对象内,然后导入,即

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

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

      import Implicits._
      

      【讨论】:

      • IIRC 您可以将导入放入包对象中,使其至少有点“全局”:-)
      【解决方案3】:

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

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

      但是代码

      2 + new Rational(1, 2)
      

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

      【讨论】:

        猜你喜欢
        • 2012-02-13
        • 2017-07-13
        • 1970-01-01
        • 1970-01-01
        • 2018-10-15
        • 2014-08-05
        • 1970-01-01
        • 1970-01-01
        • 2014-08-30
        相关资源
        最近更新 更多