Java Reference
In-Depth Information
private void writeAccountsToFile() {
accountsFile.
withWriter
{ w ->
accounts.
each
{ id, account ->
w.
println
("$id,$account.balance")
}
}
dirty = true
}
Examining the previous listing shows that I'm using
splitEachLine
and
withWriter
in the
File
class and the
println
method from the
Writer
class, so
these methods need to be implemented in the
Expando
.
All of those methods are already implemented in the
String
class. Therefore, why not
use a string to represent the file? I'll add a string property to the
Expando
and then im-
plement all the needed methods so that they delegate to the corresponding methods on the
string. Here's the resulting code:
Expando ex =
new
Expando()
ex.data = ''
ex.
println
= { data.append(it) }
ex.withWriter = {
new
StringWriter() }
ex.splitEachLine = { pattern, clos ->
data.splitEachLine(pattern, clos) }
First I instantiate the
Expando
. Next I add a
data
property to it and assign it to an
empty string. The
println
method is then implemented through the
append
method
on
String
. The
withWriter
method is assigned a closure that returns a new
StringWriter
. Finally, the
splitEachLine
method is assigned to a two-argument
closure that delegates to the corresponding existing method on
String
.
All that's left is to substitute the
Expando
for the file in the DAO:
FileAccountDAO dao =
new
FileAccountDAO(accountsFile:ex)
Here at last is the reason Ineeded to declare the
accountsFile
variable with
def
rather
than
File
. An
Expando
isn't a file and isn't related to the
File
class in any way, so
a
File
reference would be a problem. If I use
def
to declare the variable instead, I can
freely assign the
Expando
variable to my variable. Duck typing does the rest; every time
a method is invoked on the variable, the corresponding method is called on the
Expando
.