我如何链接在斯卡拉暗示?

pimp-my-library模式允许我通过从该类到实现该方法的隐式转换,向表面上看似地添加方法的类。

斯卡拉不允许两个这样的隐式转换发生,但是,我不能从AC使用隐式AB和另一个隐式BC 有没有办法解决这个限制?

Scala对自动转换有一个限制,就是添加一个方法,也就是说它不会在尝试查找方法时应用多个转换。 例如:

 class A(val n: Int) class B(val m: Int, val n: Int) class C(val m: Int, val n: Int, val o: Int) { def total = m + n + o } // This demonstrates implicit conversion chaining restrictions object T1 { // to make it easy to test on REPL implicit def toA(n: Int): A = new A(n) implicit def aToB(a: A): B = new B(an, an) implicit def bToC(b: B): C = new C(bm, bn, bm + bn) // won't work println(5.total) println(new A(5).total) // works println(new B(5, 5).total) println(new C(5, 5, 10).total) } 

编辑:视图边界('<%')已弃用自斯卡拉2.11 https://issues.scala-lang.org/browse/SI-7629 (你可以使用types类代替)

但是,如果隐式定义本身需要一个隐式参数(视图绑定),那么Scala 根据需要寻找额外的隐式值。 从最后一个例子继续:

 // def m[A <% B](m: A) is the same thing as // def m[A](m: A)(implicit ev: A => B) object T2 { implicit def toA(n: Int): A = new A(n) implicit def aToB[A1 <% A](a: A1): B = new B(an, an) implicit def bToC[B1 <% B](b: B1): C = new C(bm, bn, bm + bn) // works println(5.total) println(new A(5).total) println(new B(5, 5).total) println(new C(5, 5, 10).total) } 

“魔术师”,你可能会说。 不是这样。 下面是编译器如何翻译每一个:

 object T1Translated { implicit def toA(n: Int): A = new A(n) implicit def aToB(a: A): B = new B(an, an) implicit def bToC(b: B): C = new C(bm, bn, bm + bn) // Scala won't do this println(bToC(aToB(toA(5))).total) println(bToC(aToB(new A(5))).total) // Just this println(bToC(new B(5, 5)).total) // No implicits required println(new C(5, 5, 10).total) } object T2Translated { implicit def toA(n: Int): A = new A(n) implicit def aToB[A1 <% A](a: A1): B = new B(an, an) implicit def bToC[B1 <% B](b: B1): C = new C(bm, bn, bm + bn) // Scala does this println(bToC(5)(x => aToB(x)(y => toA(y))).total) println(bToC(new A(5))(x => aToB(x)(identity)).total) println(bToC(new B(5, 5))(identity).total) // no implicits required println(new C(5, 5, 10).total) } 

因此,当bToC被用作隐式转换时, aToBaToB被作为隐式参数传递,而不是被链接为隐式转换。

编辑

感兴趣的相关问题:

  • 关于蕴涵的types,起源和优先性的讨论

请注意,您也可以使用隐式参数构build圆。 但是,编译器会检测到这些内容,如下所示:

 class Wrap { class A(implicit b : B) class B(implicit c : C) class C(implicit a : A) implicit def c = new C implicit def b = new B implicit def a = new A } 

虽然给用户的错误不是那么清楚, 它只是抱怨could not find implicit value for parameter三个build筑工地的could not find implicit value for parameter 。 这可能会在不太明显的情况下掩盖潜在的问题。

这是一个代码,也积累了path。

 import scala.language.implicitConversions // Vertices case class A(l: List[Char]) case class B(l: List[Char]) case class C(l: List[Char]) case class D(l: List[Char]) case class E(l: List[Char]) // Edges implicit def ad[A1 <% A](x: A1) = D(xl :+ 'A') implicit def bc[B1 <% B](x: B1) = C(xl :+ 'B') implicit def ce[C1 <% C](x: C1) = E(xl :+ 'C') implicit def ea[E1 <% E](x: E1) = A(xl :+ 'E') def pathFrom(end:D) = end pathFrom(B(Nil)) // res0: D = D(List(B, C, E, A))