zero_cool zero_cool - 1 year ago 82
Groovy Question

Groovy make a class implement an interface via metaprogramming

Can I make a class implement an interface via Groovy's compile-time metaprogramming, and if so, how? I know that I can implement the methods defined in an interface for a given class. But how can I then cast an object of that class to that interface type?

Let's say I have an interface

public interface MyInterface {
void foo();

and a class

public class MyClass {


can I then provide a method
with return type
that returns an instance of
when called like

MyInterface mi = bar();;

and does not raise a

Answer Source

Groovy features a couple of runtime ways to solve that, but I'm not aware of any "compile-time" solutions to it (beside implementing the interface, of course).

Anyway, you can coerce a class/map/closure to an interface easily. Here are some solutions:

1. as operator

I think this is the best for your case. A class is coerced into an interface. It is similar to Java proxies.

interface MyInterface {
  def foo()

class MyClass {
    def foo() { "foo" }

def bar() {
    return new MyClass() as MyInterface

MyInterface mi = bar()
assert == "foo"

2. Map coercion

A map can be coerced into an interface. You need to forward the method signatures, but it also gives more control over what is invoked and how it is invoked.

def mapped() {
    def m = new MyClass()
    [foo: { }] as MyInterface

MyInterface mi2 = mapped()
assert == "foo"

3. Anonymous class

Classical JDK < 8 style for a single method interface implementation.

def anonymous() {
    def m = new MyClass()
    new MyInterface() {
        def foo() {

MyInterface mi3 = anonymous()
assert == "foo"

4. Closure coercion

This one works a lot like JDK 8 lambda coercion. In this case, the method is returning a method reference to coerced into MyInterface. Be aware closure coercion is way more powerful than this, being able to coerce into abstract classes, concrete classes and splitting the atom:

def coercion() {
    def m = new MyClass()
    m.&foo as MyInterface

MyInterface mi4 = coercion()
assert == "foo"