Groovy 使一个类通过元编程实现一个接口(interface)

标签 groovy

我能否通过 Groovy 的编译时元编程让类实现接口(interface),如果可以,如何实现?我知道我可以实现在给定类的接口(interface)中定义的方法。但是我如何才能将该类的对象转换为该接口(interface)类型呢?

假设我有一个接口(interface)

public interface MyInterface {
  void foo();
}

和一个类

public class MyClass {

}

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

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

并且不会引发 ClassCastException

最佳答案

Groovy 提供了几个运行时方法来解决这个问题。对于编译时间,@Delegate当然,除了实现接口(interface)之外,可能还有一些值得关注的地方。

无论如何,您可以轻松地将类/映射/闭包强制转换为接口(interface)。以下是一些解决方案:

1。 作为运算符

我认为这最适合您的情况。一个类被强制转换为一个接口(interface)。它类似于 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。 map 强制

map 可以强制转换为界面。您需要转发方法签名,但它也可以更好地控制调用的内容和调用方式。

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

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

3。匿名类

单一方法接口(interface)实现的经典 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对一个对象的所有方法调用,该对象可以响应所有接口(interface)而无需实现它们。

请注意,如果 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"
}

关于Groovy 使一个类通过元编程实现一个接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38913394/

相关文章:

grails - IntelliJ Idea 自动完成我自己的 grails 域元类方法?

jenkins - 使用 env groovy 文件访问 Jenkins 凭证存储 secret

java - 自定义 Grails 异常处理

groovy - 将 Jenkins Groovy Postbuild 步骤添加到所有作业

grails - 在具有equals方法的域类上, 'as JSON'出现Grails 2.5.5错误

jenkins - 执行Jenkinsfile时如何获取管道配置字段 'Script Path'?

java - 如何分隔以 "$"分隔的 java 字符串?

Groovy 元编程

grails - 使用Realm + RABBIT MQ进行Groovy Httpbuilder身份验证

grails - 什么时候在Grails框架的标签属性值中使用表达式$ {}?