当前项目的一部分涉及从耦合到数据库的类型转换和通过Json将结果序列化到客户端时使用的泛型类型,Scala中的当前实现使用类型推断来正确执行转换,使用Scala' s TypeTag:
def Transform[A: TypeTag](objects:Seq[A]):Seq[Children] = typeOf[A] match {
case pc if pc =:= typeOf[ProductCategory] =>
TransformProductCategory(objects.asInstanceOf[Seq[ProductCategory]])
case pa if pa =:= typeOf[ProductArea] =>
TransformProductArea(objects.asInstanceOf[Seq[ProductArea]])
case pg if pg =:= typeOf[ProductGroup] =>
TransformProductGroup(objects.asInstanceOf[Seq[ProductGroup]])
case psg if psg =:= typeOf[ProductSubGroup] =>
TransformProductSubGroup(objects.asInstanceOf[Seq[ProductSubGroup]])
case _ =>
throw new IllegalArgumentException("Invalid transformation")
}
用作输入的类型是所有案例类,并在应用程序内部定义,例如:
case class ProductCategory(id: Long, name: String,
thumbnail: Option[String],
image:Option[String],
sequence:Int)
这种方法虽然目前适用,但在添加可能更多的数据库类型时并不具备功能或可扩展性。我也觉得使用asInstanceOf
应该是多余的,因为类型已被断言。我对implicits的有限知识表明它们可以用来代替执行转换,并且完全不需要上面的Transform[A: TypeTag](objects:Seq[A]):Seq[Children]
方法。或者也许我应该使用不同的方法呢?
答案 0 :(得分:1)
我不确定你的程序应该如何工作完全,也不知道你的任何变换是自制类型还是你从库中提取的东西,但是我无论如何可能有解决方案
match
确实很好,case classes
因此,不是手动检查输入数据的类型,而是可以将它们全部包装在案例类中(如果您需要随身携带数据)或案例对象(如果您不是)
这样你可以这样做:
// this code assumes ProductCategory, ProductArea, etc.
// all extends the trait ProductType
def Transform(pType: ProductType): Seq[Children] = pType match {
case ProductCategory(objects) => TransformProductCategory(objects)
case ProductArea(objects) => TransformProductArea(objects)
case ProductGroup(objects) => TransformProductGroup(objects)
case ProductSubGroup(objects) => TransformProductSubGroup(objects)
}
通过将所有内容包装在案例类中,您可以准确指定要带入的数据类型,只要它们(案例类,而不是数据)都从相同的类/特征继承,就应该没事的
由于只有少数几个扩展ProductType
的课程你不需要默认情况,因为 没有默认情况!
这样做的另一个好处是,它可以无限扩展;只需添加更多案例和案例类!
请注意,此解决方案要求您重新编写代码,因此在您投入代码之前请记住这一点。
答案 1 :(得分:1)
您可以定义如下特征:
trait Transformer[A] {
def transformImpl(x: Seq[A]): Seq[Children]
}
然后你可以定义一些实例:
object Transformer {
implicit val forProduct = new Transformer[ProductCategory] {
def transformImpl(x: Seq[ProductCategory]) = ...
}
...
}
最后:
def transform[A: Transformer](objects:Seq[A]): Seq[Children] =
implicitly[Transformer[A]].transformImpl(objects)
最好,您应该在Transformer
对象或与您的类别类对应的对象中定义隐式实例。