インターフェースを実装しているクラスの一部のメソッドを差し替えるにはどうするの?

やりたい事は、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.groovy

Test.metaClass.print = { println "class custom print" } // インターフェースのメタクラスを使う
Impl i = new Impl()
i.print() // "class custom impl" が出力される。

でもこれだと Test っていうインターフェースを実装している全てのクラスのメソッドを変更してしまう。

Impl.java のコードは上と同じ
Impl2.java

public 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()