如果存在,则调用 Scala Option 值的方法

Call a method on the value of Scala Option if present

我正在尝试找出重构以下代码以消除对 Option.get() 的使用的最佳方法。我知道使用 get 方法被认为是不好的做法。

if (myConnection.isDefined) {
  myConnection.get.close
}

其中 myConnection 的类型为 Option[Connection]

getOrElse 似乎不起作用,因为没有 "else" 对象来调用该方法。如果 myConnection 是 None,那么我什么都不想做。

我想我可以像这样使用 forEach:

myConnection.foreach{ c => c.close }

这可行,但我觉得很奇怪。在我的例子中,myConnection 永远不会包含一个以上的连接,其他人后来查看我的代码可能会认为它可以包含多个连接。

有没有更好的方法做到这一点既简洁又清晰?

通常,您会映射一个 Option 以对其值进行操作。

myConnection.map(c => c.close())

myConnection.map(close(_))

如果 c 是 None 并且将 return 变成 None,那么它将什么都不做。否则,它会给你一个 Some(True) if,例如 close() returns 一个 True 当它成功时。如果 close() 没有 return 值,则映射将 return 一个具有 Option[Unit].

类型的 Some(())
当您使用 return 值 unit 进行计算时,

foreach 是有意义的,副作用。关闭连接听起来不错 foreach对我来说。

这就是 Option.foreach 的样子:

@inline final def foreach[U](f: A => U) {
  if (!isEmpty) f(this.get)
}

但是如果你想做一些计算和 return 值,.mapmatch 可能会更好。

import scala.util.Try

val connectionMaybe = Try {
  DriverManager.getConnection(
    s"jdbc:h2:~/test;MODE=Oracle",
    "sa",
    ""
  )
}.toOption


def getSomething(connectionMaybe: Option[Connection]): Option[Int] = {
  connectionMaybe match {
    case Some(connection) =>
      val statement = connection.createStatement()
      val rs = statement.executeQuery(s"select * from something")
      Option(rs.getInt("some_column"))
      //cleanup if needed
    case _ =>
      println("no connection found")
      None
  }
}

模式匹配版本,如果你不喜欢纯函数 foreach/map 调用:

myConnection match {
  case Some(conn) => 
    conn // TODO add logic here, `con` is unwrapped here
  case None => 
    // TODO add error-back logic here
}