groovy提供了一些非常方便的方法来实现接口
只有一个方法的接口可以使用闭包来实现,例如
<code>1</code>
<code>// a readable puts chars into a charbuffer and returns the count of chars added</code>
<code>2</code>
<code>def</code> <code>readable = { it.put(</code><code>"12 34"</code><code>.</code><code>reverse</code><code>()); </code><code>5</code> <code>} </code><code>as</code> <code>readable</code>
<code>3</code>
<code>4</code>
<code>// the scanner constructor can take a readable</code>
<code>5</code>
<code>def</code> <code>s = </code><code>new</code> <code>scanner(readable)</code>
<code>6</code>
<code>assert</code> <code>s.nextint() == </code><code>43</code>
当然也可以使用闭包来实现不止一个方法的接口.这个闭包将会被这个接口的所有的方法调用.例如:
<code>interface</code> <code>x {</code>
<code> </code><code>void</code> <code>f()</code>
<code> </code><code>void</code> <code>g(</code><code>int</code> <code>n)</code>
<code> </code><code>void</code> <code>h(string s, </code><code>int</code> <code>n)</code>
<code>}</code>
<code>7</code>
<code>x = {object[] args -> </code><code>println</code> <code>"method called with $args"</code><code>} </code><code>as</code> <code>x</code>
<code>8</code>
<code>x.f()</code>
<code>9</code>
<code>x.g(</code><code>1</code><code>)</code>
<code>10</code>
<code>x.h(</code><code>"hello"</code><code>,</code><code>2</code><code>)</code>
通常情况下,接口中都会包含多个方法,我们可以使用map来实现接口,比如:
<code>impl = [</code>
<code> </code><code>i: </code><code>10</code><code>,</code>
<code> </code><code>hasnext: { impl.i > </code><code>0</code> <code>},</code>
<code> </code><code>next: { impl.i-- },</code>
<code>]</code>
<code>iter = impl </code><code>as</code> <code>iterator</code>
<code>while</code> <code>( iter.hasnext() )</code>
<code> </code><code>println</code> <code>iter.next()</code>
请注意,这是一个有点做作的例子,但说明了这个概念。
你只需要实现接口中会被调用的方法, 如果你调用了一个在map中并不存在的方法的话,那么将会抛出nullpointerexception 异常。 例如:
<code>interface</code> <code>x</code>
<code>{ </code><code>void</code> <code>f(); </code><code>void</code> <code>g(</code><code>int</code> <code>n); </code><code>void</code> <code>h(string s, </code><code>int</code> <code>n); }</code>
<code>x = [ f: {</code><code>println</code> <code>"f called"</code><code>} ] </code><code>as</code> <code>x</code>
<code>//x.g() // npe here</code>
你能猜出下面的代码做了什么么?
<code>x = { f: {</code><code>println</code> <code>"f called"</code><code>} } </code><code>as</code> <code>x</code>
我们在这里定义的是一个闭包,一个标签一个代码块,我们刚刚定义了一个每个接口方法都会调用的闭包, 一些语言使用{}来定义map,所以这可能误导你,请记住在groovy中定义map使用[:]。
注意:使用as操作符需要你有一个你打算使用map实现的接口的静态引用。如果你有一个代表你想实现的接口的java.lang.class 对象的引用,你就可以如同下面的方式一样使用astype 方法:
<code>def</code> <code>loggerinterface = class.forname( </code><code>'my.loggerinterface'</code> <code>)</code>
<code>def</code> <code>logger = [</code>
<code> </code><code>log : { object[] params -> </code><code>println</code> <code>"log: ${params[0]}"</code><code>;</code><code>if</code><code>( params.length > </code><code>1</code> <code>) params[</code><code>1</code><code>].printstacktrace() },</code>
<code> </code><code>close : { </code><code>println</code> <code>"logger.close called"</code> <code>}</code>
<code> </code><code>].astype( loggerinterface )</code>
see also:
<a href="http://groovy.codehaus.org/developer+testing+using+closures+instead+of+mocks">developer testing using closures instead of mocks</a>