ExpandoMetaClass.enableGlobally と disableGlobally

型に対するメタクラスとインスタンスに対するメタクラスで遊んでたら例外がでた - お だ のスペース の続きです。
ExpandoMetaClass.enableGlobally()について一言いっておくか - uehaj's blog にて、uehaj さんが解説してくれました。
ExpandoMetaClass (Groovy 1.6.5) enableGlobally メソッド を呼び出したら問題無いそうです。
早速試してみました。

ExpandoMetaClass.enableGlobally()

class Test {
  void print() {
    println 'Print'
  }
}

def t = new Test()
t.print() // print
Test.metaClass.print = { println 'Class Custom Print' }
t.print() // Class Custom Print
new Test().print() // Class Custom Print
t.metaClass.print = { println 'Instance Custom Print' }
t.print() // Instance Custom Print
new Test().print() // Class Custom Print

例外が出てたのは、ExpandoMetaClass になってて欲しいのに MetaClassImpl のままだから出てたのかな?
ExpandoMetaClass.enableGlobally() を呼んで、あらかじめ ExpandoMetaClass にしておけば、インスタンスメタクラスでメソッドを上書きしても例外が出なくなりました。
ExpandoMetaClass.enableGlobally() は、インスタンスの生成前に呼び出さないとダメでした。ExpandoMetaClass.enableGlobally() を呼び出した後で生成されたインスタンスメタクラスが ExpandoMetaClass になるのみたい。


あと、diableGlobally() っていうメソッドもあったんだけど、こっちは enableGrobally() を無効にするのかと思って少し試してみた。

disableGlobally を呼び出す前にメタクラスを参照する

ExpandoMetaClass.enableGlobally()
class Test {
  void print() {
    println 'Print'
  }
}
println Test.metaClass // ExpandoMetaClass
ExpandoMetaClass.disableGlobally()
class Test2 {
  void print() {
    println 'Print'
  }
}
println Test.metaClass // ExpandoMetaClass
println Test2.metaClass // HandleMetaClass

disableGlobally を呼び出す前にメタクラスを参照しない

ExpandoMetaClass.enableGlobally()
class Test {
  void print() {
    println 'Print'
  }
}
// println Test.metaClass
ExpandoMetaClass.disableGlobally()
class Test2 {
  void print() {
    println 'Print'
  }
}
println Test.metaClass // HandleMetaClass
println Test2.metaClass // HandleMetaClass

disableGlobally を呼び出さない

ExpandoMetaClass.enableGlobally()
class Test {
  void print() {
    println 'Print'
  }
}
println Test.metaClass // ExpandoMetaClass
// ExpandoMetaClass.disableGlobally()
class Test2 {
  void print() {
    println 'Print'
  }
}
println Test.metaClass // ExpandoMetaClass
println Test2.metaClass // ExpandoMetaClass

disableGlobally を呼び出す前にメタクラスを参照すると disableGlobally を呼び出しても、ExpandoMetaClass から変わりません。一度設定した値は、戻らないって事でしょうか。