1

我有一个迭代器,我想允许客户端以不同类型格式化。例如,我想要一个看起来像这样的界面:

val results = new Results[Integer](Seq(1,2,3,4))  
results.foreach(print)     // Prints 1, 2, 3, 4

val jsResults = results.as[JsArray]
jsResults.foreach(print)   // Prints [ [1], [2], [3], [4] ] 

results.as[String].foreach(print)  // Prints "1", "2", "3", "4"
results.as[HTML].foreach(print)    // Prints <tr><td>1</td><td>2</td>...</tr>

什么是优雅的类设计来实现这一点?我采用的方法是一个抽象的结果类,每个结果类型都有子类。所以像:

abstract class Results[T](...)
class JsonResults extends Results[JsArray]
class StringResults extends Results[String]
class HTMLResults extends Results[HTML]

但是我无法在abstract class Results给定结果类型的情况下实现返回正确子类的函数。这是我到目前为止所拥有的,但我得到了所有类型的编译错误:

abstract class Results[T](...) {
   def as[A : ClassTag]: Result[A] = implicitly[ClassTag[A]] = {
      case implicitly[ClassTag[JsArray]] => new JsonResults(...)
      ...
   }
}

错误看起来像:

[error]  found   : JsonResults
[error]  required: Result[A]
[error]     case implicitly[ClassTag[JsArray]] => new JsonResults(...)

如果有什么我可以澄清的,请告诉我。

4

1 回答 1

0

您正朝着正确的方向前进,使用隐式构造类型类。

您可能会在优秀的 sjson 库中看到示例。

给定的示例是根据执行转换的类型参数化的。您应该在目标类型上添加第二个参数化:

trait Writes[T, R] {
  def writes(o: T): R
}

def serialize[T,R](o: T)(implicit wrt: Writes[T,R]): R = wrt.writes(o)

并且您应该为相应的协议编写实现,如上面链接的示例中

于 2013-07-21T00:22:20.477 回答