加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 为什么这些隐式转换导致循环代码

发布时间:2020-12-16 08:49:54 所属栏目:安全 来源:网络整理
导读:考虑使用 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 de
考虑使用 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

解决方法

不好,但我绝对不会称之为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)
}

(好吧,这只是一张地图(toB)).无论如何,两个相互递归的含义可能会发生同样的情况.在我看来,调整规范是不值得的,只是为了避免在其他许多方面编写无限循环,不做任何循环.但是当检测到这样的循环时,无论含义如何,都会发出警告.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读