uehaj's blog

Grな日々 - GroovyとかGrailsとかElmとかRustとかHaskellとかReactとかFregeとかJavaとか -

Expandoとは何か

Expandoはマップの様に動作するオブジェクト(orオブジェクトの様に動作するマップ)である。マップの要素にクロージャを代入するとメソッドの様に動作する。マップの要素に値を代入すると、そのフィールドがあるかのように動作する。Expandoはas演算子によりマップからas演算子で変換することで生成可能(Expandoから継承した新たなクラスを作っても良いけどマップから変換したほうが簡単)。

マップの要素に代入したクロージャのスコープはもともとのレキシカルスコープに加えて、Expando内のメソッド名やフィールド名が見えるようになる(delegateに割り当てられる)。

まとめると、Groovyでは本来オブジェクトとマップは別物なのだが、それを混同できるようなオブジェクトがExpando。ちなみにJavaScriptのオブジェクトはもともとこんな風になってる(すべてがExpando)。

s=[ f:{g()},
    g:{"hoge"}] as Expando

assert s.f() == "hoge"

def method(x) {
  def n = 3
  x.d = { n }
  x.e = { g() }
}

method(s)
assert s.d() == 3
assert s.e() == "hoge"

てな感じでしょうか。