Scala隐式对象 vs 隐式值

21

我见过两种在Scala中为类型类模式声明implicit的方法(一种比另一种少一些)。

implicit val instance1 = new Typeclass { def do = ??? }
implicit object instance2 extends Typeclass { def do = ??? }

它们有什么不同?是否应该根据特定情况偏好其中之一?我发现implicit valimplicit object更常用,而且我还没有找到很多关于implicit object的资源。

1个回答

15

一个区别是object版本将会被惰性初始化,也就是说它的构造函数只有在第一次使用时才会调用。例如:

trait Incrementer[T] {
  def inc(x: T)
}

def increment[T](x: T)(implicit ev: Incrementer[T]) = ev.inc(x)

implicit object IntIncrementer extends Incrementer[Int] {
  println("IntIncrementer is being constructed...")

  def inc(x: Int) = x + 1
}

implicit val DoubleIncrementer extends Incrementer[Double] {
  println("DoubleIncrementer is being constructed...")

  def inc(x: Double) = x + 1D
}

请注意,只有当 IntIncrementer 被使用时,您才能看到来自它的消息。
increment(1)  //this prints "IntIncrementer is being constructed..."
< p > 然而,来自 < code > DoubleIncrementer 的消息将在其定义时显示。因此, < code > implicit object 的初始化是延迟的,而 < code > implicit val 的初始化是严格的。 < /p >

1
那么,使用 implicit 对象还是 val 取决于您是更喜欢惰性初始化还是严格初始化? - Kevin Meredith
6
这可能是其中一个考虑因素(尽管您可以始终使用lazy val来获得带有val的惰性),但并不是唯一的考虑因素。例如,子类可以重写val成员,而无法重写object成员。我相信还有很多其他区别。 - Jason Scott Lenderman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接