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

scala – 隐式转换导致无限递归,但不应该进行类型检查

发布时间:2020-12-16 09:59:41 所属栏目:安全 来源:网络整理
导读:我正在尝试为一个以Squants Time作为参数的类编写Specs2测试.诀窍是两个工具都定义了一个隐式,它添加了一个名为“秒”的方法,将一个数字转换成它们自己的表示形式(一个案例中为squants.time.Seconds,另一个案例中为org.specs2.time.Duration),不幸的是,错误
我正在尝试为一个以Squants Time作为参数的类编写Specs2测试.诀窍是两个工具都定义了一个隐式,它添加了一个名为“秒”的方法,将一个数字转换成它们自己的表示形式(一个案例中为squants.time.Seconds,另一个案例中为org.specs2.time.Duration),不幸的是,错误的似乎优先.

val a = new MyClass(10 seconds)  // doesn't build because MyClass wants a Time instead of a Duration

要清楚,我可以通过不依赖于暗示来构建Squants时间来解决这个问题,这不是问题.

我更喜欢implicits所以我决定添加一个隐式转换持续时间到Times:

implicit def specsTimeToSquantsTime(t: org.specs2.time.Duration): squants.time.Time = squants.time.Seconds(t.toSeconds)

这让它得到了类型检查,但是当我运行测试时,我得到了一个堆栈溢出并且堆栈跟踪没有很大意义,它说我的隐式转换是在调用自己(这不会出现问题,即使是鉴于以上代码,它仍然是不可能的!):

[error] package.TestConversions$.specsTimeToSquantsTime(TestConversions.scala:9)
[error] package.TestConversions$.specsTimeToSquantsTime(TestConversions.scala:9)
[error] package.TestConversions$.specsTimeToSquantsTime(TestConversions.scala:9)
...

所以我有三个问题:这里发生了什么?有一个更好的方法吗?我可以手动隐藏Int =>持续时间吗?

解决方法

方法toSeconds在Time类中定义:

final class Time private (val value: Double) extends Quantity[Time] {    
  ...
  def toSeconds = to(Seconds)
  ...
}

https://github.com/garyKeorkunian/squants/blob/master/src/main/scala/squants/time/Time.scala

因此,当编译器看到在Duration上调用此方法时 – 它正在搜索适当的隐式和它的specsTimeToSquantsTime,它依次包含Duration.toSeconds,这需要从Duration到Time的隐式转换,依此类推.所以你在运行时得到了无限的递归调用,这在编译器方面是完全正确的,理论上你可以停止这种递归,并且没有通用的方法(见halting problem)来检测它.

您可以在规范中混合使用NoTimeConversions特征以避免隐式转换:

This trait can be used to deactivate the time conversions (to avoid conflicts with Akka’s conversions for example

(编辑:李大同)

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

    推荐文章
      热点阅读