Groovy って private が使えないの?

private final なのに書き込めてしまいました o...rz

class Person {
  private final name = 'foo', age = 30
}

p = new Person()

p.name = 'hoge'          // private final なのに書き込める。
assert p.name == 'hoge'

p.age  = 20
assert p.age == 20       // private final なのに書き込める。

assert 'hoge' == p.@name               // フィールドが直接変更されていることを確認。
assert 'hoge' == p.getProperty('name') // 明示的にプロパティとしてアクセスしても同様であることを確認。

GROOVY-3010: fix private field visibility によると、2.0まで修正されないらしいです。


とりあえず、以下のように setter に final をつけると回避可能。でも、エラーにはなりません。

class Person {
  private final name = 'foo', age = 30
  final setName(name) {}
}
p = new Person()
p.name = 'hoge'                       // エラーにはならない。
assert 'foo' == p.name                // 値は変更されていない。
assert 'foo' == p.@name               // 値は変更されていない。
assert 'foo' == p.getProperty('name') // 値は変更されていない。


エラーにしたいのであれば、以下のようにすればOK。

class Person {
  private final name = 'foo', age = 30
  final setName(name) { throw new IllegalStateException() }
}

でも、こんなこと気にするなら素直に java 使えよという気がするw


おいらはスクリプト言語も使っているのであまり気にならないけど*1java オンリーの人から見たらこれって致命的なバグですよね。

でも、おいら的には(今のところ)groovy に期待しているのはシンタクティック・シュガーだけなので、まあいいかw

    • -

こんな感じで喧々諤々としてたのねん。
:GROOVY-1063: No access protection for private static fields
:GROOVY-1591 Private Fields Are Accessible From Other Classes
:GROOVY-1875 private fields and private methods are not private

*1:クラスもインスタンスも単なる連想配列で、メソッドも変数も単なるデータだよね〜的なノリは嫌いじゃないですw。保守が必要なソースをそのノリで書かれると死人が出ますが o...rz