是否有机会从N个混合大小写类中创建新的可实例化类或类型?

时间:2018-08-09 17:15:21

标签: scala reflection metaprogramming

假设我有如下案例类:

!this.state.showForm

现在,我想将这些类合并为新类,并在不编写另一类的情况下创建该类型的实例:

case class Id(id: Long)
case class Department(number: Long)
case class Employee(name: String, surname: String)

type UberEmployee = Employee with Department with Id
val uberEmployeeInstance = new UberEmployee("Jon", "Smith", 1200, 1) 

是否有可能通过元编程或反射在Scala中实现此目标?在我想象中的情况下,带有mixins的类组合对我不起作用。

1 个答案:

答案 0 :(得分:1)

用继承实际上不能完成,因为只有特征支持多重继承,所以最好的办法是自动生成转换方法。我认为您可以通过反射或某种代码生成来实现。但是,最简单的方法可能是使用shapeless。实际上,这是一个shapeless guide(第75页)中的例子:

import shapeless._
import shapeless.ops.hlist._

trait Migration[A, B] {
  def apply(a: A): B
}

implicit class MigrationOps[A](a: A) {
  def migrateTo[B](implicit migration: Migration[A, B]): B = migration(a)
}

implicit def genericMigration[A, B, ARepr <: HList, BRepr <: HList](
  implicit aGen: LabelledGeneric.Aux[A, ARepr], bGen: LabelledGeneric.Aux[B, BRepr],
  inter: Intersection.Aux[ARepr, BRepr, BRepr]): Migration[A, B] = new Migration[A, B] {
  def apply(a: A): B = bGen.from(inter(aGen.to(a)))
}

然后只需使用所有相关字段定义“超级”类,然后调用.migrateTo

case class UberEmployee(id: Long, number: Long, name: String, surname: String)

UberEmployee(123, 456, "John", "Doe").migrateTo[Employee]  // returns Employee("John", "Doe")