天天看点

groovy-实现接口

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 -&gt; </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 &gt; </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 -&gt; </code><code>println</code> <code>"log: ${params[0]}"</code><code>;</code><code>if</code><code>( params.length &gt; </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>