考虑一下Scala中的以下代码:
object Test {
class A {}
class B extends A {}
class AI extends A {
def sayHello: String = "Hello from AI"
}
implicit def AtoAI(a: A): AI = a
class BI extends B {
def sayHello: String = "Hello from BI"
}
implicit def BtoBI(b: B): BI = b
def main(args: Array[String]) {
val a = new A
println(a.sayHello)
val b = new B
println(b.sayHello)
}
}使用implicits会导致代码循环。事实上,反汇编显示,生成的转换方法内部只有一个goto 0:
public Test$AI AtoAI(Test$A);
Code:
0: goto 0
public Test$BI BtoBI(Test$B);
Code:
0: goto 0是什么导致了这种行为?我知道,这里的类层次结构是可疑的,但隐式转换应该只应用一次。
我使用Scala 2.9.1
发布于 2012-01-13 20:23:41
不是很好,但我绝对不会称它为bug。
归根结底就是
class A
class B
implicit def aToB(a: A) : B = a转换的两个方面没有必要以任何方式相关。隐含和写作是一回事。
implicit def aToB(a: A): B = aToB(a)因为编译器插入aToB调用以便将结果a转换为所需的返回类型B。
goto 0实现只是一个尾部调用优化。编译器在生成以这种方式启动的方法时可能会给出警告。
也许有一条规则是,隐式方法在其自身内部不能作为隐式方法使用。但它并不总是创建无限循环。
implicit def listAToListB(l: list[A] = l match {
case Nil => Nil
case x:xs => toB(x) :: xs // equivalent to toB(x) :: listAToList[B](xs)
}(好的,这只是一个map(toB))。无论如何,两个相互递归的隐含也会发生同样的事情。在我看来,仅仅为了避免写一个无限的、不做任何事情的循环等等的可能性而调整规范是不值得的。但是,当检测到这样的循环时发出警告,无论是否隐含,都是很好的。
https://stackoverflow.com/questions/8849491
复制相似问题