我有一个迭代器,我想允许客户端以不同的类型进行格式化。例如,我希望有一个看起来像这样的界面:
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(...)
如果有任何我可以澄清的话,请告诉我。
答案 0 :(得分:0)
使用implicits构建类型类,正朝着正确的方向前进。
您可以在优秀的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)
你应该为相应的协议编写实现,如上面链接的例子