2

scala 抽象クラスでは、コンテキスト バウンドを定義したい場合、たとえば [T: ClassTag] をパラメーターで使用できますが、これはトレイトでは不可能です。

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 を読み取ろうとすると、暗黙的なパラメーターが末尾再帰になるため、StackOverflowError がトリガーされます。

では、サブクラスをコンテキスト バインドに自動的に公開するトレイトで ctg を定義できるようにする最善の方法は何でしょうか?

4

1 に答える 1

8

うまい方法はない。コンテキスト バウンドは暗黙的なパラメーターの省略形であり、特性にはパラメーターがありません。つまり、次のように記述します。

 class Foo[T : ClasTag]

コンパイラは、次の目的でコードを de-sugar します。

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

もちろん、これは特性では不可能です。これをトレイトで回避する必要がある場合は、 ClassTagabstract を作成し、それを拡張するクラスに強制的に実装させることができます。

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

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

これは、クラスを中間に置くと少しInt良く見えるので、定義時に 2 回Bar指定する必要はありません。

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

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

object Bar extends FooImpl[Int]
于 2016-05-17T00:27:18.267 に答える