在编译时验证 Scala 案例 class

Validate Scala case class at compile time

我在 Scala 2.11 应用程序中有一个案例 classes,它有一个方法依赖于案例 class 的字段名称,如下所示:

final case class Foo(
  val a: String,
  val b: String,
  val c: String
) {
  def partitionColumns: Seq[String] = Seq("b", "c")
}

如果 partitionColumns 之一在案例 class 中不作为字段存在,我想要一个编译时检查来抛出错误,例如会捕获这个的东西:

final case class Bar(
  val a: String,
  val b: String,
  val c: String
) {
  def partitionColumns: Seq[String] = Seq("x", "y")
}

到目前为止,我已经将分区行为封装在一个特征中,这减少了 times/places 可能出错的次数:

sealed trait partitionedByBAndC {
  def b: String
  def c: String
  def partitionColumns: Seq[String] = Seq("b", "c")
}

final case class Foo(
  val a: String,
  val b: String,
  val c: String
) extends PartitionedByBAndC

但是如果trait写错了,就没有check e.g.这段代码编译得很好:

sealed trait partitionedByBAndCIncorrect {
  def b: String
  def c: String
  def partitionColumns: Seq[String] = Seq("x", "y")
}

final case class Foo(
  val a: String,
  val b: String,
  val c: String
) extends partitionedByBAndCIncorrect

在 Scala 2.13 中,我也许可以使用 productElementNames,但我使用的是 Scala 2.11(和 Spark 2.3)。如果不从 class/trait 中实际构造一个对象,我不确定该怎么做,这似乎有很多开销(考虑到代码中有许多这些特征)。

有一个小型库(scala-nameOf) 可以用来做这个:

final case class Foo(
                    val a: String,
                    val b: String,
                    val c: String
                  ) {
import com.github.dwickern.macros.NameOf._
def partitionColumns: Seq[String] = Seq(nameOf(this.a),nameOf(this.b))

}

这不会为不属于大小写的字段编译 class