在当前类的子类型上定义类型参数

时间:2014-02-21 20:22:45

标签: scala

我正在使用Scala的隐含参数,虽然我可能试图把它放得太远但是遇到了一些我似乎无法解决的问题。

我正在研究的例子非常简单:一个进程产生的结果都是同一个基类的实例,但有时可以是专用的。这些结果需要序列化为各种格式(例如,JSON和XML),这似乎是类型类的完美用例:

// All results are instances of Result.
trait Result {
  def value: String
  def count: Int
}

// Implementations are used to format results to any format that can be implemented.
trait ResultFormatter[T <: Result, B] {
  def format(t: T): B
}

// One type of result.
case class ResultA(value: String, count: Int) extends Result

// Another type of result.
case class ResultB(value: String, count: Int, details: String) extends Result


object ResultFormatter {
  // Formats a result to the appropriate type if an implicit formatter is in scope.
  def format[T <: Result, B](t: T)(implicit format: ResultFormatter[T, B]): B = format.format(t)

  // Formats instances of ResultA to strings.
  implicit val StringA = new ResultFormatter[ResultA, String] {
    override def format(a: ResultA): String = "%s (%d)" format (a.value, a.count)
  }

  // Formats instances of ResultB to strings.
  implicit val StringB = new ResultFormatter[ResultB, String] {
    override def format(b: ResultB): String = "%s (%d) [%s]" format (b.value, b.count, b.details)
  }
}

// Through the magic of implicit parameters and type classes, instances of ResultA and ResultB are formatted
// to the appropriate type without having to modify either.
println(ResultFormatter.format(ResultA("result A", 1)))
println(ResultFormatter.format(ResultB("result B", 2, "foo bar")))

但是,我真正想做的是让format成为Result的成员并允许调用,例如result.format[JObject]

trait Result {
  def value: String
  def count: Int
  def format[T <: Result, B](implicit format: ResultFormatter[T, B]): B = format.format(this)
}

但这不合法,因为thisResult的实例,而不是T的实例。

有没有办法做到这一点,或者我必须放弃想法或改变我的模型,例如它,以实现类似的功能?

1 个答案:

答案 0 :(得分:2)

试试这个:

trait Result {
  def value: String
  def count: Int
  def format[B](implicit f: ResultFormatter[this.type , B]): B = f.format(this)
}