使用反射检查至少一个案例类字段值是否为非空的scala方法

3

我有一个要求,对于一个包含大约30个Option[T]字段的给定案例类,至少需要有1个非空字段才能被视为有效。 为了不逐个检查每个字段,我选择通过反射以通用的方式检查所有字段。我想出来的代码(基于SO上的一些其他答案)是:

import scala.reflect.runtime.universe._
import scala.reflect.runtime.{universe => ru}

  // gets all methods of a Case Class
  def getMethods[T: ru.TypeTag] = typeOf[T].members.collect {
    case m: MethodSymbol if m.isCaseAccessor => m
  }.toList


  /**
    *  Returns the value of all Case Class fields
    * @param obj case class object
    * @return a Sequence of all field values
    */
  def getAllCaseClassFieldValues[T: ru.TypeTag](obj: Object): Seq[Any] = {
    val mirror = ru.runtimeMirror(getClass.getClassLoader)
    getMethods[T].map(m => mirror.reflect(obj).reflectField(m).get)
  }

案例类:

case class SampleRequest(field1: Option[String], field2: Option[String], //.... up to 30 or more fields

检查至少有一个非空的代码:
 val fieldValues = getAllCaseClassFieldValues[SampleRequest](r)
 val noneCount = fieldValues.count(_ == None)
 val atLeastOneNonEmpty = noneCount < fieldValues.size

我在想是否有更好的方式通过反射或其他机制来验证这个内容?
2个回答

10

这是一个 case class,因此它实现了 Product 特质。Product 特质有一个迭代器 def productIterator : Iterator[Any]

case class Foo(one: Option[Int], two: Option[String], three : Option[Double])

var i = Foo(None, Some("Woot!"), None)
var j = Foo(Some(1), Some("There Can Be Only"), None)
var k = Foo(None, None, None)

i.productIterator.exists(_.isInstanceOf[Some[_]]) // True
j.productIterator.exists(_.isInstanceOf[Some[_]]) // True
k.productIterator.exists(_.isInstanceOf[Some[_]]) // False

我经常在评估稀疏流数据时使用这个技巧。

4
你可以尝试这样做:
abstract class AtLeastOneNonEmptyOption[T] { self: T with Product =>

  def nonEmpty: Boolean = this.productIterator.exists {
    case Some(_) => true
    case _ => false
  }

}

case class MyClass(foo: Option[String], bar: Option[Int]) extends AtLeastOneNonEmptyOption[MyClass]

val nonEmptyClass = MyClass(Some("foo"), None)
val emptyClass = MyClass(None, None)

nonEmptyClass.nonEmpty //true
emptyClass.nonEmpty //false

也许有更好的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接