获取可选类字段的值

Gat*_*sby 1 scala

假设我有一个带有两个可选字段的Toto类:

case class Toto(a : Option[Int], b: Option[Int])
Run Code Online (Sandbox Code Playgroud)

还有一个带有一个可选Toto的Titi类:

case class Titi(c : Option[Toto])
Run Code Online (Sandbox Code Playgroud)

我们创建一个Titi类的实例:

val test = Titi(Some(Toto(Some(1),Some(2))))
Run Code Online (Sandbox Code Playgroud)

现在,我想通过假定Titi或b可以等于None来访问Titi变量中Toto的第二个字段,但这条语句是不可能的:

test.c.getOrElse("Something").b.getOrElse(0)
Run Code Online (Sandbox Code Playgroud)

我该怎么做呢?

Krz*_*sik 7

您应该使用flatMap:

test.c.flatMap(_.b).getOrElse(0)
Run Code Online (Sandbox Code Playgroud)

在层次结构中任何位置的情况下,None将返回0。如果您具有返回属性的更深层次的对象层次结构,则Option可以链接flatMap

test.c
 .flatMap(_.b)
 .flatMap(_.d)
//...etc
Run Code Online (Sandbox Code Playgroud)

Scala还具有用于解开深度嵌套的monadic类型的特殊语法,称为for comprehension

val result = for {
   c <- test.c
   a <- c.a
} yield a

result.getOrElse(0)
Run Code Online (Sandbox Code Playgroud)

在后台,它被编译为类似于chained的代码flatMap

这基本上是这样的:

如果cNone,则直接进入getOrElse并返回0;如果是,Some则进行检查b;如果不是,则进行检查;否则,返回getOrElse包装的值Some

如果您想返回不同的区别,那Option就是None,那么我将使用match

test.c match {
   case Some(c) => c.getOrElse(0)
   // if you return String in one branch and integer in other then inferred type would be Any!
   case None    => "Something" 
}
Run Code Online (Sandbox Code Playgroud)