Groovy让一个类通过元编程来实现一个接口 [英] Groovy make a class implement an interface via metaprogramming

查看:126
本文介绍了Groovy让一个类通过元编程来实现一个接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



假设我有一个接口

  public interface MyInterface {
void foo();
}

和一个类

  public class MyClass {

}



然后,我可以提供一个返回类型 MyInterface 的方法 bar ,它返回一个 MyClass 当被调用时像

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

并且不会引发 ClassCastException

解决方案

Groovy提供了几种运行时解决方法。对于编译时, @Delegate 可能是需要看的东西,当然除了实现接口。

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

1。 作为运算符



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

 接口MyInterface {
def foo()
}

class MyClass {
def foo(){foo}
}

def bar(){
返回new MyClass()as MyInterface
}


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



2。地图强制



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

  def mapped (){
def m = new MyClass()
[foo:{m.foo()}]作为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强制。在这种情况下,该方法返回一个方法引用,将其转换为 MyInterface 中的 m.foo 。请注意,关闭强制的方式比这更强大,可以强制进入抽象类,具体类和拆分原子

  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()}
$ b $ class MyClass {
def foo(){foo }
def bar(){bar}
def baz(){baz}
}

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

class MyDelegate实现Foo,Bar,Baz {
@Delegate MyClass我的

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

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


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 bar with return type MyInterface that returns an instance of MyClass when called like

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

and does not raise a ClassCastException?

解决方案

Groovy features a couple of runtime ways to solve that. For compile time, @Delegate may be something to look at, besides 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 mi.foo() == "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: { m.foo() }] as MyInterface
}

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

3. Anonymous class

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

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

MyInterface mi3 = anonymous()
assert mi3.foo() == "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 m.foo 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 mi4.foo() == "foo"

5. @Delegate with a factory for subclasses

Update: You can create a class which @Delegates all method invocations to an object which can respond to all interfaces without implementing them.

Note that if MyClass doesn't implement all needed methods, a compilation error is thrown.

For subclasses, you can use a factory method:

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让一个类通过元编程来实现一个接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆