用于将数据转换为多种类型之一的设计模式[Scala]

时间:2013-07-20 20:11:49

标签: scala generics

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

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(...)

如果有任何我可以澄清的话,请告诉我。

1 个答案:

答案 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)

你应该为相应的协议编写实现,如上面链接的例子