如何在Scala中编写类析构函数?

时间:2010-10-23 03:35:53

标签: scala destructor

我想在一个类实例存在的整个过程中打开一个FileWriter。所以我需要在析构函数中关闭它。但是如何在Scala中指定析构函数?

4 个答案:

答案 0 :(得分:10)

您可能有兴趣查看Josh Suereth的scala-arm项目,该项目仅针对此使用来源提供基于monadic和delimited-continuation的资源管理:http://github.com/jsuereth/scala-arm

如果你真的认为你需要一个析构函数(也就是因为你认为你需要创建该对象,然后将其交给它再也不会再看到它)我建议重新考虑你的应用程序架构......根本就没有在JVM上可靠地工作的方法。

答案 1 :(得分:8)

这是我经常使用的一种方便的实用方法。我发现它很好地整理了我的代码。

def closer [T, C <: Closeable] (c : C) (f : C => T) : T = 
    try f (c)
    finally c.close

使用它很简单。下面的示例使用来自URLConnection的输入流。您可以创建任何任意流,而不是connection.getInputStream(或者更常见的是,任何可任意的可关闭对象)。

val bytes = closer (connection.getInputStream) { istream =>
        val bytes = new ByteArrayOutputStream ()
        val buffer : Array [Byte] = new Array (1024)
        Iterator.continually (istream read buffer).takeWhile (_ > 0).foreach (bytes write (buffer, 0, _))
        bytes.toByteArray
    }

此版本将使用close方法操作(无需实现Closeable或其他任何内容)。

def autoClose[R <: {def close()}, T](resource: R)(use: R => T): T = {
  try use(resource)
  // Don't want an NPE here masking an exception from use.
  finally Option(resource).foreach(_.close())
}

以下是一些隐含的类来完成这项工作。

implicit class AutoCloseBracket[R <: Closeable](resource: R) {
  def autoClose[V](use: R => V): V = try use(resource) finally resource.close()
}
implicit class AutoCloseableBracket[R <: AutoCloseable](resource: R) {
  def autoClose[V](use: R => V): V = try use(resource) finally resource.close()
}

答案 2 :(得分:7)

Scala没有析构函数。它有终结器,如Java,但它们根本不是一回事。还有一个有趣的博客系列在此处模拟Scala中的C#using关键字:

答案 3 :(得分:2)

如上所述,Java有一个专门针对IO的现有Closeable接口,您可以采用。这不会提供任何糖,但它会帮助人们正确使用你的课程。

在Java 7中,Closeable将是AutoCloseable的子接口。 AutoCloseable是一个更通用的接口,用于在使用后需要关闭的任何资源,同时可能引发异常。它是Java 7中计划的Automatic Resource Management支持的一部分。与您的问题不太相关(因为您使用的是Scala),也应该是新的Java syntax(现有try块的扩展)对于这种情况。