Java Scala Monad-无for语句(检查null属性的优雅方式)

Java Scala Monad-无for语句(检查null属性的优雅方式),java,scala,monads,Java,Scala,Monads,假设我只有一个顶级对象,另两个对象嵌套在其中作为属性: class Human(val name: String, val child: Human) val anita = new Human("Anita", null) val david = new Human("David", anita) val fabrizio = new Human("Fabrizio", david) 如果我必须将最后一个孩子的名字从fabrizio开始,我需要执行许多空检查控件: if(fabrizio

假设我只有一个顶级对象,另两个对象嵌套在其中作为属性:

class Human(val name: String, val child: Human)

val anita = new Human("Anita", null)
val david = new Human("David", anita)
val fabrizio = new Human("Fabrizio", david)
如果我必须将最后一个孩子的名字从fabrizio开始,我需要执行许多空检查控件:

if(fabrizio != null)
    if(fabrizio.child!= null)
        if(fabrizio.children.child!= null)
            println(fabrizio.child.child.name)
我在scala上发现了这个“语法糖”,但它似乎只适用于集合:

println( for(x <- fabrizio.child; y <- x.child; z <- y.child) yield z.name)

有没有一种方法可以在不将顶级对象放入集合的情况下获取最后一个子名称?

它不是集合独有的。用于理解的Scalas将desugas转换为嵌套的
flatMap
调用和最终的
map
。不要在代码中使用
null
,而是使用
选项[T]
来表示一个事实,即
人及其子项可以定义,也可以不定义:

final case class Human(name: String, children: Option[Human])
val maybeAnita: Option[Human] = Some(Human("Anita", None))
val maybeDavid: Option[Human] = Some(Human("David", maybeAnita))
val maybeFabrizio: Option[Human] = Some(Human("Fabrizio", maybeDavid))
现在您可以:

val maybeName: Option[String] = for {
  fabrizio <- maybeFabrizio
  children <- fabrizio.children
  nestedChildren <- children.children
} yield nestedChildren.name
val-maybeName:Option[String]=for{

fabrizio它不是集合独有的。用于理解的Scalas将desugars转换为嵌套的
flatMap
调用和最终的
map
。不要在代码中使用
null
,而是使用
选项[T]
来表达这样一个事实,即
人及其子代可能被定义,也可能未被定义:

final case class Human(name: String, children: Option[Human])
val maybeAnita: Option[Human] = Some(Human("Anita", None))
val maybeDavid: Option[Human] = Some(Human("David", maybeAnita))
val maybeFabrizio: Option[Human] = Some(Human("Fabrizio", maybeDavid))
现在您可以:

val maybeName: Option[String] = for {
  fabrizio <- maybeFabrizio
  children <- fabrizio.children
  nestedChildren <- children.children
} yield nestedChildren.name
val-maybeName:Option[String]=for{

fabrizioYuval建议使用
选项
是处理
null
的惯用、简单的方法,是一个极好的建议。我想补充一下:

如果要查找最后一个子项的名称,只需创建一个函数:

def lastChild(person: Human, isChild: Boolean = false): Option[Human] = {
    person.children match {
        case Some(child) => lastChild(child, true)
        case None if isChild => Some(person)
        case _ => None
    }
}
您还可以添加一个级别变量以确保特定的生成:

def nthChild(person: Human, level: Int, isChild: Boolean = false): Option[Human] = {
    person.children match {
        case Some(child) if (level > 0) => lastChild(child, (level - 1), true)
        case _ if ((level == 0) && isChild) => Some(person)
        case _ => None
    }
}


另请注意:如果每个
人类
只能有一个孩子,为了清晰起见,该字段应命名为
child

尤瓦尔建议使用
选项
,这是处理
的惯用、简单的方法,是一个极好的建议。我想补充一点:

如果要查找最后一个子项的名称,只需创建一个函数:

def lastChild(person: Human, isChild: Boolean = false): Option[Human] = {
    person.children match {
        case Some(child) => lastChild(child, true)
        case None if isChild => Some(person)
        case _ => None
    }
}
您还可以添加一个级别变量以确保特定的生成:

def nthChild(person: Human, level: Int, isChild: Boolean = false): Option[Human] = {
    person.children match {
        case Some(child) if (level > 0) => lastChild(child, (level - 1), true)
        case _ if ((level == 0) && isChild) => Some(person)
        case _ => None
    }
}

旁注:如果每个
人类
只能有一个孩子,为了清楚起见,该字段应命名为
child