Scala 对象转换的隐式类型推理
当前项目的一部分涉及从耦合到数据库的类型和通过Json将结果序列化到客户端时使用的泛型类型转换,Scala中的当前实现使用类型推断来正确执行转换,使用Scala的TypeTag:Scala 对象转换的隐式类型推理,scala,implicits,Scala,Implicits,当前项目的一部分涉及从耦合到数据库的类型和通过Json将结果序列化到客户端时使用的泛型类型转换,Scala中的当前实现使用类型推断来正确执行转换,使用Scala的TypeTag: def Transform[A: TypeTag](objects:Seq[A]):Seq[Children] = typeOf[A] match { case pc if pc =:= typeOf[ProductCategory] => TransformProductCategory(objec
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)
这种方法虽然目前适用,但在可能添加更多的DB类型时感觉不到功能性或可伸缩性。我还觉得使用
asInstanceOf
应该是多余的,因为类型已经被断言了。我对隐式的有限了解表明,可以使用隐式来执行转换,并且完全不需要上述转换[A:TypeTag](objects:Seq[A]):Seq[Children]
方法。或者也许我应该用另一种方法来代替 我不确定你的程序到底应该如何工作,也不知道你的任何转换是自制类型还是从库中提取的东西,不过我可能有一个解决方案
一些匹配
非常好用的东西是案例类
所以,不必手动检查输入数据的类型,您可以将它们全部包装在case类(如果您需要携带数据)或case对象(如果您不需要)中
这样,您可以执行以下操作:
// 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)
}
trait Transformer[A] {
def transformImpl(x: Seq[A]): Seq[Children]
}
通过将所有内容包装在一个case类中,您可以精确地指定要携带的数据类型,只要它们(case类,而不是数据)都继承自同一个类/特征,就可以了
由于只有少数几个类扩展了ProductType
,所以不需要默认情况,因为没有默认情况
另一个好处是,它可以无限扩展;只需添加更多案例和案例类
请注意,此解决方案需要您对代码进行大量重构,因此在投入其中之前,请牢记这一点。您可以定义如下特征:
// 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)
}
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
对象或与您的类别类对应的对象中定义隐式实例。我不明白为什么人们更喜欢def transform[A:Transformer](对象:Seq[A]):Seq[Children]=隐式[Transformer[A].def transform[A]之上的transformImpl(对象)
(对象:Seq[A])(隐式t:Transformer[A])=t.transformImpl(对象)
。。。从长远来看,不断被迫隐式地使用[]
肯定会变得非常陈旧,所以为什么不让Scala自动执行呢?