确定子类中的非空附加字段

Rak*_*ith 0 scala traits scala-option

假设我有一个看起来像这样的特征

trait MyTrait {
  val x: Option[String] = None
  val y: Option[String] = None
}
Run Code Online (Sandbox Code Playgroud)

发布定义特征我将此特征扩展到一个MyClass看起来像这样的类

case class MyClass(
  override val x: Option[String] = None, 
  override val y: Option[String] = None, 
  z: Option[String] = None
) extends MyTrait
Run Code Online (Sandbox Code Playgroud)

现在我需要查找除了由MyTraitis not扩展的属性之外的任何其他属性None。从某种意义上说,如果我需要编写一个被调用的方法,该方法getClassInfo根据案例类中存在的值返回真/假。在这种情况下,如果z是非可选的,它应该返回 true 。我getClassInfo的事情是这样的

def getClassInfo(myClass: MyClass): Boolean = {
  myClass
    .productIterator
    .filterNot(x => x.isInstanceOf[MyTrait])
    .exists(_.isInstanceOf[Some[_]])
}

Run Code Online (Sandbox Code Playgroud)

理想情况下,这应该过滤掉所有不属于的字段,Mytraitz在这种情况下返回我。我尝试使用方差,但似乎isInstanceOf不一样

filterNot(x => x.isInstanceOf[+MyTrait])
Run Code Online (Sandbox Code Playgroud)

然而这是不可能的

val a = getClassInfo(MyClass()) //Needs to return false
val b = getClassInfo(MyClass(Some("a"), Some("B"), Some("c"))) //returns true
val c = getClassInfo(MyClass(z = Some("z"))) //needs to return true
val d = getClassInfo(MyClass(x = Some("x"), y = Some("y"))) // needs to return false
Run Code Online (Sandbox Code Playgroud)

Tim*_*Tim 6

简单的答案是声明一个抽象方法,该方法给出您想要的结果并在子类中覆盖它:

trait MyTrait {
  def x: Option[String]
  def y: Option[String]
  def anyNonEmpty: Boolean = false
}

case class MyClass(x: Option[String] = None, y: Option[String] = None, z: Option[String] = None) extends MyTrait {
  override def anyNonEmpty = z.nonEmpty
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以调用anyNonEmpty您的对象以获取getClassInfo结果。

另请注意,由于初始化问题,我在def这里使用了trait因为valin atrait通常是一个坏主意。