やりたい事は、Java で宣言されているインターフェースとそれを実装したクラスがあって、インターフェースで宣言されている一部のメソッドの実装を差し替えたい。
このコードでうまくいかない。
Impl.java
interface Test { void print(); } public class Impl implements Test { public void print() { System.out.println("impl"); } }GTest.groovy
Impl.metaClass.print = { println "class custom print" } Impl i = new Impl() // i.metaClass.print = { println "instance custom print" } i.print() // 型のメタクラス、インスタンスのメタクラスどちらを使った場合でも "impl" が出力される。
このコードだと、一応うまくいく
Impl.java のコードは上と同じ
GTest.groovyTest.metaClass.print = { println "class custom print" } // インターフェースのメタクラスを使う Impl i = new Impl() i.print() // "class custom impl" が出力される。
でもこれだと Test っていうインターフェースを実装している全てのクラスのメソッドを変更してしまう。
Impl.java のコードは上と同じ
Impl2.javapublic class Impl2 implements Test { public void print() { System.out.println("impl2"); } }GTest.groovy
Test.metaClass.print = { println "class custom print" } Impl i = new Impl() i.print() // "class custom impl" が出力される。 Impl2 i2 = new Impl2() i2.print() // "class custom impl" が出力される。
どうしたらいいんだろう?ちなみに Groovy だけでも同じでした。
interface Test { void print() } class Impl implements Test { void print() { println "impl" } } class Impl2 implements Test { void print() { println "impl2" } } // Test.metaClass.print = { println "class custom print" } // インターフェースのメタクラスだと、実装している全ての型のメソッドが変更される def i = new Impl(); // i.metaClass.print = { println "instance custom print" } // インスタンスのメタクラスでは、動作が変わらない。 i.print() // // Impl2.metaClass.print = { println "instance custom print" } // 型のメタクラスでは、動作が変わらない。 def i2 = new Impl2(); i2.print()