考虑使用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)
}
}
Run Code Online (Sandbox Code Playgroud)
使用implicits会导致循环代码.事实上,反汇编表明,生成的转换方法只有一个goto 0内部:
public Test$AI AtoAI(Test$A);
Code:
0: goto 0
public Test$BI BtoBI(Test$B);
Code:
0: goto 0
Run Code Online (Sandbox Code Playgroud)
是什么导致这种行为?我理解,这里的类层次结构是可疑的,但隐式转换只应用一次.
我使用Scala 2.9.1
Did*_*ont 12
不好,但我绝对不会称之为bug.
归结为
class A
class B
implicit def aToB(a: A) : B = a
Run Code Online (Sandbox Code Playgroud)
转换的双方无需以任何方式相关.隐含与写作是一回事
implicit def aToB(a: A): B = aToB(a)
Run Code Online (Sandbox Code Playgroud)
因为编译器插入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)
}
Run Code Online (Sandbox Code Playgroud)
(好吧,这只是一个map(toB)).无论如何,两个相互递归的暗示也会发生同样的情况.在我看来,调整规范是不值得的,只是为了避免一些写无限循环的可能性,以及其他许多循环.但是当检测到这样的循环时,无论含义如何,都会发出警告.
| 归档时间: |
|
| 查看次数: |
290 次 |
| 最近记录: |