Reputation: 2672
I was looking for an implementation of the Execute Around method pattern in scala, and found the following (with my minor mods):
class Resource private() {
private def dispose() { println("Cleaning up...") }
def example = {
println("Function body")
}
}
object Resource {
def using(codeBlock: Resource => Unit) {
val run = new Resource
try {
codeBlock(run)
}
finally {
run.dispose()
}
}
}
Resource.using { run => run.example }
Then I had second thoughts about using it for my particular application, since that's a lot of boilerplate code in all my classes.
I was wondering if the more experienced scala gurus were able to create a similar pattern, and wrap an entire object, calling a cleanup method when the object goes out of scope? This would be similar to the C# using() block, and I'd implement it by mixing in a Disposable trait to the objects that would support this method?
Example goal:
trait Disposable { def dispose }
class a extends Disposable
[some helper object unrelated to a?].using (a) {
} // automatically call a.dispose() at end of scope?
Upvotes: 0
Views: 205
Reputation: 3398
From this blog post you can implement something like Java's try with resources this way:
class Loan[A <: AutoCloseable](resource: A) {
def to[B](block: A => B) = {
var t: Throwable = null
try {
block(resource)
} catch {
case x: Exception => t = x; throw x
} finally {
if (resource != null) {
if (t != null) {
try {
resource.close()
} catch {
case y: Exception => t.addSuppressed(y)
}
} else {
resource.close()
}
}
}
}
}
object Loan {
def loan[A <: AutoCloseable](resource: A) = new Loan(resource)
}
you would use it like this:
loan (new PrintWriter(new File("file"))) to (_ println "Hello world!\n")
Using the Java AutoCloseable interface for this means that your objects can be used in a Java try-with-resources block and that you can use your helper with standard Java AutoCloseable things like IO streams.
Upvotes: 2