首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这些隐式转换会导致代码循环

为什么这些隐式转换会导致代码循环
EN

Stack Overflow用户
提问于 2012-01-13 18:57:30
回答 1查看 294关注 0票数 7

考虑一下Scala中的以下代码:

代码语言:javascript
复制
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

代码语言:javascript
复制
public Test$AI AtoAI(Test$A);
  Code:
   0:   goto    0

public Test$BI BtoBI(Test$B);
  Code:
   0:   goto    0

是什么导致了这种行为?我知道,这里的类层次结构是可疑的,但隐式转换应该只应用一次。

我使用Scala 2.9.1

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-01-13 20:23:41

不是很好,但我绝对不会称它为bug。

归根结底就是

代码语言:javascript
复制
class A

class B

implicit def aToB(a: A) : B = a

转换的两个方面没有必要以任何方式相关。隐含和写作是一回事。

代码语言:javascript
复制
implicit def aToB(a: A): B = aToB(a)

因为编译器插入aToB调用以便将结果a转换为所需的返回类型B

goto 0实现只是一个尾部调用优化。编译器在生成以这种方式启动的方法时可能会给出警告。

也许有一条规则是,隐式方法在其自身内部不能作为隐式方法使用。但它并不总是创建无限循环。

代码语言:javascript
复制
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))。无论如何,两个相互递归的隐含也会发生同样的事情。在我看来,仅仅为了避免写一个无限的、不做任何事情的循环等等的可能性而调整规范是不值得的。但是,当检测到这样的循环时发出警告,无论是否隐含,都是很好的。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8849491

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档