用Groovy的方式实现接口

Groovy提供了一些非常方便的方式来实现接口。

用闭包实现接口

如果一个接口只有一个方法,那么可以使用闭包来实现,如下:

new Thread(
  {println "running"} as Runnable
).start()

你也可以使用闭包来实现一个含有多个方法的接口,此时闭包将被接口上的每个方法调用。有时候你需要一个含有参数列表的闭包来满足所有的方法,那么使用一个数组类型的参数是典型的做法,而且此做法可以在任意的Groovy闭包上使用,Groovy会将所有的参数放到一个数组当中,比如:

interface X
{ void f(); void g(int n); void h(String s, int n); }
 
x = {Object[] args -> println "method called with $args"} as X
x.f()
x.g(1)
x.h("hello",2)

用映射实现接口

通常含有多个方法的接口一般是用映射来实现,比如:

impl = [
  i: 10,
  hasNext: { impl.i > 0 },
  next: { impl.i-- },
]
iter = impl as Iterator
while ( iter.hasNext() )
  println iter.next()

:!:注意 这是一个非常人为的例子,但确实解释了概念。

一般来说你只需要实现那些你实际调用的方法即可,但是如果调用一个在map中不存在的方法,将抛出NullPointerException异常,比如:

interface X
{ void f(); void g(int n); void h(String s, int n); }
 
x = [ f: {println "f called"} ] as X
x.f()
//x.g()    // NPE here空指针

要注意:!:不要偶尔使用{}来定义map,你能猜出下面代码将会是什么结果么?

x = { f: {println "f called"} } as X
x.f()
x.g(1)

此处我们定义了一个带标签和代码块的闭包,由于我们在此只是定义了一个闭包,因此每一个方法调用都将调用此闭包。某些语言是使用{ }来定义映射的,因此很容易跟Groovy的定义映射([:])的方式混淆。

注意:!:在上述示例中,“as”操作符的使用将要求我们用映射实现的接口有一个静态的引用(static reference 即要知道接口的类型,译者注)。如果只有一个java.lang.Class对象的引用来表示要用到的接口(比如根本不知道或者不想在脚本里边硬编码)呢?那你可以使用asType方法来实现,如下:

def loggerInterface = Class.forName( 'my.LoggerInterface' )
def logger = [
               log : { Object[] params -> println "LOG: ${params[0]}"; if( params.length > 1 ) params[1].printStackTrace() },
               close : { println "logger.close called" }
             ].asType( loggerInterface )

更多参考:

 
wiki/user_guide/groovy_way_to_implement_interfaces.txt · 最后更改: 2008-04-19 13:50 (外部编辑)
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki