C# 有 using
与 IDisposable
界面。 Java 7+ 具有与 try
相同的功能和 AutoCloseable
界面。 Scala 允许您选择自己的实现来解决这个问题。
scala-arm 似乎是流行的选择,由 Typesafe 的一名员工维护。但是,对于这样一个简单的行为,它似乎非常复杂。澄清一下,使用说明很简单,但了解所有代码在内部是如何工作的却相当复杂。
我刚刚写了以下 super 简单的ARM解决方案:
object SimpleARM {
def apply[T, Q](c: T {def close(): Unit})(f: (T) => Q): Q = {
try {
f(c)
} finally {
c.close()
}
}
}
最佳答案
这里是我较新的简单、一目了然的Scala ARM。这完全支持我能想到的每个用例,包括多个资源和 yield 值。这使用了一个非常简单的理解用法语法:
class AutoCloseableWrapper[A <: AutoCloseable](protected val c: A) {
def map[B](f: (A) => B): B = {
try {
f(c)
} finally {
c.close()
}
}
def foreach(f: (A) => Unit): Unit = map(f)
// Not a proper flatMap.
def flatMap[B](f: (A) => B): B = map(f)
// Hack :)
def withFilter(f: (A) => Boolean) = this
}
object Arm {
def apply[A <: AutoCloseable](c: A) = new AutoCloseableWrapper(c)
}
这是演示使用:
class DemoCloseable(val s: String) extends AutoCloseable {
var closed = false
println(s"DemoCloseable create ${s}")
override def close(): Unit = {
println(s"DemoCloseable close ${s} previously closed=${closed}")
closed = true
}
}
object DemoCloseable {
def unapply(dc: DemoCloseable): Option[(String)] = Some(dc.s)
}
object Demo {
def main(args: Array[String]): Unit = {
for (v <- Arm(new DemoCloseable("abc"))) {
println(s"Using closeable ${v.s}")
}
for (a <- Arm(new DemoCloseable("a123"));
b <- Arm(new DemoCloseable("b123"));
c <- Arm(new DemoCloseable("c123"))) {
println(s"Using multiple resources for comprehension. a.s=${a.s}. b.s=${b.s}. c.s=${c.s}")
}
val yieldInt = for (v <- Arm(new DemoCloseable("abc"))) yield 123
println(s"yieldInt = $yieldInt")
val yieldString = for (DemoCloseable(s) <- Arm(new DemoCloseable("abc")); c <- s) yield c
println(s"yieldString = $yieldString")
println("done")
}
}
关于scala - "using/try-with-resources"的简单 Scala 模式(自动资源管理),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25634455/