Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala:如何检查类中是否至少定义了一个字段?_Scala_Reflection_Field_Optional - Fatal编程技术网

Scala:如何检查类中是否至少定义了一个字段?

Scala:如何检查类中是否至少定义了一个字段?,scala,reflection,field,optional,Scala,Reflection,Field,Optional,我有一个类,它有几个可选字段,如下所示: class Container(f1: Option[String] = None, f2: Option[Boolean] = None, f3: Option[Int] = None, f4: Option[String] = None // ... 30 other fields which is unfortunate/

我有一个类,它有几个可选字段,如下所示:

class Container(f1: Option[String] = None,
                f2: Option[Boolean] = None,
                f3: Option[Int] = None,
                f4: Option[String] = None
                // ... 30 other fields which is unfortunate/terrible and
                // cannot be changed at the moment
                 ) {
  def hasAtleastOneDefinedField: Boolean = {
    this.f1.isDefined ||
      this.f2.isDefined ||
      this.f3.isDefined ||
      this.f4.isDefined
    // this is too-much of boilerplate
  }

  // This is something along the lines of what I want
  def hasAtleastOneDefinedField2: Boolean = {
    // this.getAllDeclaredFields.find(field => field.value.isDefined)
    ???
  }
}

在不使用反射的情况下也可以这样做吗?

不确定这能为您节省多少,但是:

  val hasAtLeastOneDefinedField = List(f1, f2, f3, ..., f35).exists { _.isDefined }

不要认为除了反射/宏之外还有其他方法。

只是一个想法,但根据您的预期用途,可能有一些值得考虑的设计模式可以让您的意图更加清晰

例如,如果您试图确定是否有足够的数据来构造某个对象,那么一个选项是构建器模式,例如:

object ContainerBuilder() {
  def fromF1(f1: F1) = Container(f1 = Some(f1))
  def fromF2(f2: F2) = Container(f2 = Some(f2))
  ...
}
如果您只允许以这种方式构建容器实例(例如,容器类的构造函数仅对构建器可见),那么您可以确保它们正好有一个字段集(有多种方法可以扩展此方法以生成具有多个字段集的容器,例如,请参见下文)

这可以扩展到,例如,确保在创建容器之前设置了2、3、…、所有字段。例如:

class ContainerBuilder(f1: Option[String] = None,
                       f2: Option[Boolean] = None,
                       f3: Option[Int] = None,
                       f4: Option[String] = None,
                       ...,
                       fieldsSet = 0) {
  // return a copy of this ContainerBuilder - holding any fields already set - 
  // with f1 now set, and the count of set fields incremented: 
  def fromF1(f1: F1) = copy(f1 = Some(f1), fieldsSet = fieldsSet + 1)

  // Likewise but setting the f2 field:
  def fromF2(f2: F2) = copy(f2 = Some(f2), fieldsSet = fieldsSet + 1)

  ...

  def build = if (readyToBuild) Container(f1,f2,...) else ... // for 'unready' cases, you can throw an exception, or change build to return an Option[Container], or whatever.

  def readyToBuild = fieldsSet > 2 // Ensures at least 3 fields set - change to whatever criteria you need.
}

还有几种方式可以表达这一点:

val o1 = None
val o2 = None
val o3 = Option("o")

o1.orElse(o2).orElse(o3).isDefined

List(o1, o2, o3).flatten.nonEmpty

反思并不是那么糟糕。从以下内容开始:
weakTypeOf[Container].typeSymbol.asClass.typeSignature.members
-您将获得所有字段的符号(+您应该过滤掉的更多内容)。然后将带有宏的字段重新创建为值列表,并检查是否存在非空字段。