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 で何か手が入っているのか?暇な時に調べる。