型に対するメタクラスとインスタンスに対するメタクラスで遊んでたら例外がでた - お だ のスペース の続きです。
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 // HandleMetaClassdisableGlobally を呼び出す前にメタクラスを参照しない
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 // HandleMetaClassdisableGlobally を呼び出さない
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 から変わりません。一度設定した値は、戻らないって事でしょうか。