开发者

How to write a class destructor in Scala?

开发者 https://www.devze.com 2023-01-20 21:12 出处:网络
I\'d like to have a FileWriter opened during the whole time a class instance exists. So I need to close it in a destructor. But how to specify 开发者_高级运维a destructor in Scala?You might be interes

I'd like to have a FileWriter opened during the whole time a class instance exists. So I need to close it in a destructor. But how to specify 开发者_高级运维a destructor in Scala?


You might be interested to check out Josh Suereth's scala-arm project, which provides both monadic and delimited-continuation based resource management for just this source of use: http://github.com/jsuereth/scala-arm

If you really think that you need a destructor (i.e. because you think you need to create the object and then hand it off and never see it again) I'd recommend reconsidering your application architecture instead... there is simply no way to make this work reliably on the JVM.


Here's a handy utility method I use frequently. I find that it unclutters my code nicely.

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

Using it is dead simple. The example, below, consumes an input stream from a URLConnection. Instead of connection.getInputStream you could create any arbitrary stream, of course (or, more generally, any arbitrary closeable object).

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
    }

This version will operate on anything with a close method (needn't implement Closeable or anything else).

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())
}

Here are some implicit classes to do the job.

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()
}


Scala doesn't have destructors. It has finalizers, like Java, but they're not the same thing at all. There is also an interesting blog series in emulating C#'s using keyword in Scala here:

  • Hey Scala, Finalize This
  • Scala Using RAISIN
  • More Scala Using RAISIN


As I noted above, Java has an existing Closeable interface specifically for IO, which you could adopt. This doesn't provide any sugar, but it will help people use your class correctly.

In Java 7, Closeable will be a subinterface of AutoCloseable. AutoCloseable is a more general interface for any resource that needs to be closed after use while potentially throwing an exception. it is part of the planned Automatic Resource Management support in Java 7. Less relevant to your question (since you're using Scala), there is also supposed to be new Java syntax (an extension of existing try blocks) for this scenario.

0

精彩评论

暂无评论...
验证码 换一张
取 消