Scala で後処理の省力化がしたい

Ruby の後処理省力化のイディオム

  • 「openしたら必ずclose」するために・・・
    • openにブロックを渡す
    • ブロックでは、対象リソースを引数に与える
    • openは、ブロック評価後にensureでcloseをする

上記実装

irb(main):001:0> class Foo
irb(main):002:1>   def open
irb(main):003:2>     p "opened!"
irb(main):004:2>     if block_given?
irb(main):005:3>       begin
irb(main):006:4*         yield self
irb(main):007:4>       ensure
irb(main):008:4*         close
irb(main):009:4>       end
irb(main):010:3>     end
irb(main):011:2>   end
irb(main):012:1>   def close; p "closed!"; end
irb(main):013:1>   def foo_test; p "foo_test!"; end
irb(main):014:1> end
=> nil
irb(main):015:0>
irb(main):016:0* class Bar < Foo
irb(main):017:1>   def bar_test; p "bar_test!"; end
irb(main):018:1> end
=> nil
irb(main):019:0>
irb(main):020:0* Bar.new.open { |b| b.foo_test }
"opened!"
"foo_test!"
"closed!"
=> nil
irb(main):021:0> Bar.new.open { |b| b.bar_test }
"opened!"
"bar_test!"
"closed!"
=> nil
irb(main):022:0>

ブロック内で対象を操作することで、
open ===> 何かの処理 ===> close
と、比較的安全に操作できている。

Scala で上記を実装してみる

scala> class Foo {
     |   def open = println("opened!")
     |   def open(block: (Foo) => Unit) {
     |     open
     |     try {
     |       block(this)
     |     } finally {
     |       close
     |     }
     |   }
     |   def close = println("closed!")
     |   def fooTest = println("fooTest!")
     | }
defined class Foo

scala> class Bar extends Foo {
     |   def barTest = println("barTest!")
     | }
defined class Bar

scala> (new Bar).open { _.fooTest }
opened!
fooTest!
closed!

scala> (new Bar).open { _.barTest }
<console>:8: error: value barTest is not a member of Foo
       (new Bar).open { _.barTest }
                          ^

scala>

エラーが発生している
ブロック(便宜上 ruby に合わせてこう呼んでおく)内部で barTest が呼べない

理由

Foo#open に渡しているブロックの型
  def open(block: (Foo) => Unit) {

引数の型が Foo である => Bar クラス独自のメソッドが呼べない

こうすれば桶

クラス定義は割愛

scala> val bar = new Bar
bar: Bar = Bar@f87478

scala> bar.open { b => bar.barTest }
opened!
barTest!
closed!

scala>

この場合はもはや、引数の意味がないなぁと。

Closeable 系のクラスは scala で何か手が入っているのか?暇な時に調べる。