无法在单例对象中找到隐式值

2024-07-04

我有这个代码:

trait Context {
  implicit val e: Encoder

  trait Encoder {
    def write(): Unit = {
      println("Test")
    }
  }

}

trait AsyncEncoders {
  this: Context =>

  class AsyncEncoder extends Encoder {
  }

  implicit val e = new AsyncEncoder()
}

class ConcreteContext extends Context with AsyncEncoders {
}

当我像这样使用它时(case 1):

object Main extends App {
  implicit val c = new ConcreteContext()

  import c._

  implicitly[Encoder].write()
}

然后编译并打印Test.

但是当我尝试在单例对象中调用相同的代码时(case 2):

object TestObject {
  def apply()(implicit c: ConcreteContext): Unit = {
    import c._
    implicitly[Encoder].write()
  }
}

object Main extends App {
  implicit val c = new ConcreteContext()

  TestObject()
}

编译失败并显示:

path/to/Main.scala:29: 找不到参数 e 的隐式值:c.Encoder 隐式[c.Encoder].write()

如果我改变(case 3):

implicit val e = new AsyncEncoder()

to

implicit val e: Encoder = new AsyncEncoder()

然后它会按预期编译并运行。

但由于某种原因,这对我来说是不能接受的。

为什么在上述情况下编译会失败?


我认为问题不在于你使用对象的事实,而在于你接受ConcreteContext,作为参数:ConcreteContext.e的类型是AsyncEncoder, not Encoder.

我多次观察到,当谈到 Scala 时,除非另有说明,否则最好将参数视为不变量(例如,如果不将 impl 类型转换为接口类型,macwire 经常会失败 - 但它并不是完全可预测的,大多数情况下)它工作的时间)。

正如您观察到的那样,将 e 类型显式设置为Encoder会解决这个问题。改变也是如此ConcreteContext to Context。我的猜测是,这要么是编译器类型推断引擎的不变性问题,要么是限制问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法在单例对象中找到隐式值 的相关文章

随机推荐