在编译时验证 Scala 案例类

Mic*_*l K 3 scala case-class scala-2.11 apache-spark

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

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

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

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

Run Code Online (Sandbox Code Playgroud)

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

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

Run Code Online (Sandbox Code Playgroud)

但是如果 trait 写错了,就没有检查,例如这段代码,它编译得很好:

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
Run Code Online (Sandbox Code Playgroud)

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

Rap*_*oth 5

有一个小型库(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))
Run Code Online (Sandbox Code Playgroud)

}

这不会为不属于 case 类的字段编译