【问题标题】:Why can't I embed implicit calls为什么我不能嵌入隐式调用
【发布时间】:2019-09-15 05:13:33
【问题描述】:

假设我有以下内容:

class A {
    def foo() = { println("foo") }
}

case class B(a: A)

implicit def toA(b: B) = b.a

implicit def wrapper(a: A) = new {
    def bar() = a.foo()
}

那么我不能执行以下操作:

val b = B(new A())
b.bar() // cannot resolve

我需要显式调用 toA() 隐式:

toA(b).bar()

或者做

(b: A).bar()

为什么编译器不知道在应用第二个隐式包装器之前应用第一个隐式?

【问题讨论】:

  • 这需要两个隐式解决方案。我猜编译器只是在一次隐式解析后放弃了——如果它更努力地尝试,编译可能需要更长的时间。此外,恕我直言,依赖于两个隐式使得代码很难推理,隐式转换本身也被认为是一种不好的做法。为什么不简单的给B直接添加一个扩展方法foo呢?
  • 不幸的是,我所拥有的场景不允许对 B 进行修改 - 这就像我可以制作的示例一样简单。
  • 我的意思是implicit class BOps (val b: B) extends AnyVal { def foo(): = b.a.bar() }

标签: scala implicit-conversion implicit


【解决方案1】:

一次一个规则:只尝试一个隐式。编译器永远不会将x + y 重写为convert1(convert2(x)) + y。这样做会导致错误代码的编译时间显着增加,并且会增加程序员编写的内容与程序实际执行的内容之间的差异。出于理智的考虑,当编译器已经在尝试另一个隐式转换时,它不会插入进一步的隐式转换。但是,可以通过让implicits 接受隐含参数来规避这个限制,这将在本章后面进行介绍。

21.2 Rules for implicits 部分,来自 Scala 编程,First Edition 作者:Martin Odersky、Lex Spoon 和 Bill Venners。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多