Shorthand 用于定义特征中绑定的 Scala 上下文

Shorthand for defining scala context bound in trait

在 scala abstract class 中,如果你想定义一个上下文绑定,你可以简单地使用,例如[T: ClassTag] 在参数中,但是这在 trait:

中是不可能的
trait Foo[T: ClassTag]

Error:(11, 35) traits cannot have type parameters with context bounds `: ...' nor view bounds `<% ...'
trait Foo[T: ClassTag]
         ^

如果您定义:

trait Foo[T] {

  implicit def ctg: ClassTag[T] = implicitly[ClassTag[T]]
}

object Bar extends Foo[Int]

那么任何在 Bar 中读取 ctg 的尝试都会触发 WhosebugError,因为隐式参数变为尾递归。

那么,允许在自动将子classes 暴露给上下文绑定的特征中定义 ctg 的最佳方法是什么?

没有好的方法。上下文绑定是隐式参数的简写,特征没有参数。也就是说,当你写:

 class Foo[T : ClasTag]

编译器将您的代码脱糖为:

 class Foo[T](implicit ev: ClassTag[T])

这当然不可能有特质。如果你 必须 解决这个问题,你可以使 ClassTag 抽象,并强制 class 扩展它来实现它:

trait Foo[T] {
  implicit def ctg: ClassTag[T]
}

object Bar extends Foo[Int] {
  implicit val ctg = classTag[Int]
}

这看起来略微更好,中间有一个class,这样你就不需要在定义[=16时指定两次Int =]:

trait Foo[T] {
  implicit def ctg: ClassTag[T]
}

class FooImpl[T](implicit val ctg: ClassTag[T]) extends Foo[T]

object Bar extends FooImpl[Int]