Groovy通过元编程使类实现接口

时间:2016-08-12 08:30:13

标签: groovy

我可以通过Groovy的编译时元编程实现一个类实现一个接口,如果是的话,怎么做?我知道我可以实现给定类的接口中定义的方法。但是,我怎样才能将该类的对象强制转换为该接口类型?

我们说我有一个界面

public interface MyInterface {
  void foo();
}

和一个班级

public class MyClass {

}

然后我可以提供一个返回类型为bar的方法MyInterface,该方法在调用时返回MyClass的实例,如

MyInterface mi = bar();
mi.foo();

并且没有提出ClassCastException

1 个答案:

答案 0 :(得分:5)

Groovy提供了几种运行时方法来解决这个问题。在编译时,除了实现接口之外,@Delegate可能需要注意。

无论如何,您可以轻松地将类/ map / closure强制转换为接口。以下是一些解决方案:

1。 as运营商

我认为这对你的情况最好。一个类被强制进入一个接口。它类似于Java proxies

interface MyInterface {
  def foo()
}

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

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


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

2。地图强制

地图可以强制进入界面。您需要转发方法签名,但它还可以更好地控制调用的内容以及调用方式。

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

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

3。匿名类

经典JDK<单一方法接口实现的8种风格。

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

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

4。关闭强制

这个很像JDK 8 lambda强制。在这种情况下,该方法将方法引用返回m.foo强制转换为MyInterface。请注意闭合强制比这更强大,能够强制进入abstract classes, concrete classes and splitting the atom

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

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

5。 @Delegate带有子类的工厂

更新:您可以创建一个类@Delegates对对象的所有方法调用的类,它可以响应所有接口而不实现它们。

请注意,如果MyClass没有实现所有需要的方法,则会抛出编译错误。

对于子类,您可以使用工厂方法:

interface Foo { def foo() }
interface Bar { def bar() }
interface Baz { def baz() }

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

class MySubClass extends MyClass {
    def foo() { "sub foo" }
}

class MyDelegate implements Foo, Bar, Baz {
    @Delegate MyClass my

    static getSub() {
        new MyDelegate(my : new MySubClass())
    }
}

MyDelegate.sub.with {
    assert foo() == "sub foo"
    assert bar() == "bar"
    assert baz() == "baz"
}