使用scala隐式向库添加方法

时间:2012-02-26 10:23:03

标签: scala implicit-conversion

我想在库类中添加新功能“extra”(例如“orig”)。

orig.extra(rich.Arg()) // <- like this

如果我评论第一次隐式转换而不是我得到错误。我阅读了Scala规范,并怀疑隐式查找有两个地方:

  1. 参数的伴随对象

  2. 持有参数的对象

  3. 任何提示?不幸的是,关于隐式的大多数官方文档都不是很有帮助,堆栈溢出搜索也是如此。

    scala> object container {
     |   //implicit def orig2rich(o: orig.type) = new { def extra(a: rich.Arg) = "extra" }
     |   object rich {
     |     implicit def orig2rich(o: orig.type) = new { def extra(a: Arg) = "extra" }
     |     case class Arg(val some: String = "some")
     |     object Arg {
     |       implicit def orig2rich(o: orig.type) = new { def extra(a: Arg) = "extra" }
     |     }
     |   }
     |   object orig {
     |     def standard(s: String) = "standard"
     |   }
     |   orig.extra(rich.Arg())
     | }
    <console>:35: error: value extra is not a member of object container.orig
         orig.extra(rich.Arg())
    

    修改

    我读了Where does Scala look for implicits?,非常有用。并找到我的案例 - 论证类型的隐含范围

    工作的例子:

    object container {
    class A(val n: Int) {
      def +(other: A) = new A(n + other.n)
    }
    object A {
      implicit def fromInt(n: Int) = new A(n)
    }
    
    // This becomes possible:
    1 + new A(1)
    // because it is converted into this:
    A.fromInt(1) + new A(1)
    }
    

    改变它,只是改变功能名称(我真正想要的),并且:-( oops

    object container {
    class A(val n: Int) {
      def hello(other: A) = new A(n + other.n)
    }
    object A {
      implicit def fromInt(n: Int) = new A(n)
    }
    
    // This becomes possible:
    1.hello(new A(1))
    // because it is converted into this:
    A.fromInt(1).hello(new A(1))
    }
    
    <console>:16: error: value hello is not a member of Int
           1.hello(new A(1))
    

    Scala版本2.9.1.r0-b20120114153402(OpenJDK 64位服务器VM,Java 1.6.0_22)。

    有点令人困惑。我试着混合

    7.3视图

    1. 如果选择器m不表示成员,则选择e为具有类型T的e of。在这种情况下,搜索适用于e及其结果的视图v 包含一个名为m的成员。搜索按照隐式的情况进行 参数,其中隐式范围是T的一个。如果找到这样的观点, 选择e.m转换为v(e).m。
    2. 在e选择e.m(args)中,如果选择器m表示某些内存,则 但是,这些成员都不适用于参数args。在 在这种情况下,搜索的视图v适用于e且其结果为 得到一个适用于args的方法m。搜索按照中的进行 隐式参数的情况,其中隐式范围是
    3. 之一

      恕我直言,这是不可能的

      谢谢

2 个答案:

答案 0 :(得分:2)

scala正在应用在同一范围内可见的隐式转换,因此您只需添加行

即可
import rich.orig2rich

import rich._

此代码可以使用

object container {

  //implicit def orig2rich(o: orig.type) = new { def extra(a: rich.Arg) = "extra" }
  object rich {
    implicit def orig2rich(o: orig.type) = new {
      def extra(a: Arg) = "extra"
    }

    case class Arg(val some: String = "some")

    object Arg {
      implicit def orig2rich(o: orig.type) = new {
        def extra(a: Arg) = "extra"
      }
    }

  }

  object orig {
    def standard(s: String) = "standard"
  }

  import rich.orig2rich

  def test = orig.extra(rich.Arg())
}

println(container.test)

答案 1 :(得分:0)

问题可能是origrichrichimplicit def的加载顺序。

顺便说一下,以下代码运行正常,我首先定义orig而不是rich,最后将implicit转换应用于pimp orig

object container {
    object orig {
            def standard(s:String) = "standard"
    }

    object rich {
            case class Arg(val some: String = "some")

            object Arg {
                    implicit def orig2rich(o: orig.type) = new { def extra(a: Arg) = "extra" }
            }
    }

    implicit def orig2rich(o: orig.type) = new { def extra(a: rich.Arg) = "extra" }

    orig.extra(rich.Arg())
}

println(container.orig.extra(container.rich.Arg()))