I have a use case where
name = Person.getFirstSister().getname()
Person.getSister().getname()
gives java.lang.NullPointerException
since Person.getSister()
is java null
What is the right way to do this in scala. I am able to achieve with below code. But looking for more scala way of doing it.
private def getFirstSisterName(person: Person): String = {
val sister = person.getFirstSister()
if (sister == null) ""
else sister.getName()
}
CodePudding user response:
Checking for null
is the Java way to go. Scala offers a much more streamlined set of operations to avoid doing null checks manually.
Naturally, getSister
should result in an Option[Sister]
, the argument being that not every person has a sister.
Going on the same idea, trying to mimic the real word, I would ask: but what if a person has multiple sisters? How do you distinguish between them? This implies your design is not very general because it implies every person has a sister.
So the idiomatic way is to have the method return a List[Sisters]
. Then map
their names from the list. If the list is empty, Nil
, the empty list will be the result, so we won't have any NPE:
case class Sister(name: String)
case class Person(sisters: List[Sister]) {
def sistersNames: String = sisters.map(_.name).mkString(" ")
}
val p = Person(List(Sister("Sandra"), Sister("Joanna")))
val p2 = Person(List.empty)
println(p.sistersNames) // Sandra Joanna
println(p2.sistersNames) // empty String
EDIT:
If you can't change Person
or Sister
, the alternative is to make your wrapper method to treat the null case. You can do this in 2 ways, either use pattern matching, or wrap the result in an Option
.
Note: Option(x)
checks if the code is null and if it is, it converts it to a None
. That is why applying fold
works.
private def getFirstSisterName(person: Person): String =
person.getFirstSister match {
case s: Sister => s.name
case _ => s"${person.toString} does not have a sister"
}
private def getFirstSisterName2(person: Person): String = {
val sis = Option(person.getFirstSister)
sis.fold(s"${person.toString} does not have a sister")(_.name)
}
val p = new Person(new Sister("Sandra"))
val p2 = new Person(null)
println(getFirstSisterName(p)) // Sandra
println(getFirstSisterName2(p)) // Sandra
println(getFirstSisterName(p2)) // person827966648 does not have a sister
println(getFirstSisterName2(p2)) // person827966648 does not have a sister