如何在Groovy中定义匿名内部类?我看到了他们应该在Groovy 1.7中支持的引用,我使用的是1.8。
thread = process.consumeProcessOutput(
new Appendable() {
Appendable append(char c) {
app1.append(c)
app2.append(c)
return this
}
Appendable append(CharSequence csq) {
app1.append(csq)
app2.append(csq)
return this
}
Appendable append(CharSequence csq, int start, int end) {
app1.append(csq, start, end)
app2.append(csq, start, end)
return this
}
})
我使用此代码获得异常:
Caught: groovy.lang.MissingMethodException: No signature of method: java.lang.UNIXProcess.consumeProcessOutput() is applicable for argument types: (MyClass$1) values: [MyClass$1@19c8ef56]
答案 0 :(得分:6)
这是一个棘手的情况,因为方法必须将对象本身作为Appendable
返回,并且具有重载的方法名称,这对于groovy map to interface casting不起作用。最简单,最清晰的方法可能是使用匿名内部类,就像在Java中一样。这需要一个合理的当前版本的groovy(1.7或更新我认为):
def testAppendable(Appendable appendable) {
println "appendable = $appendable"
appendable.append('a' as char).
append('b' as char).
append('c' as char)
}
testAppendable(new Appendable() {
Appendable append(char c) {
println "got $c"
this
}
Appendable append(CharSequence csq) {
this
}
Appendable append(CharSequence csq, int start, int end) {
this
}
String toString() { "inner class appendable" }
});
另一种选择是使用带有闭包的Expando
。这有点尴尬,因为每个方法名称只能在构造函数中初始化一个实现。请注意,省略的任何接口方法都会被赋予一个抛出异常的默认实现。
testAppendable(new Expando(
append: { char c ->
println "got $c"
delegate as Appendable
},
toString: { ->
"expando appendable"
}
) as Appendable)
编辑:关于你的例子,我不明白为什么会失败。我的测试几乎完全相同,没有任何问题。 process.consumeProcessOutput
的签名是什么样的?此外,您可以通过运行MyClass$1
来仔细检查Appendable
实施javap MyClass$1
。
答案 1 :(得分:3)
作为@ataylor's solution above的补充, 可以使用Map as Appendable
表示法,但它有点像软糖:
鉴于测试功能:
def testAppendable(Appendable appendable) {
println "appendable = $appendable"
appendable.append('a' as char).
append("GROOVY",1,2).
append("TIM")
}
我们可以这样构建我们的Appendable:
def app
app = [ append:{ a, b=null, c=null ->
if( a.grep( CharSequence ) ) a = a[ (b?:0)..<(c?:a.length()) ]
println "Got $a"
app
} ] as Appendable
然后,执行
testAppendable( app )
打印
appendable = {append=ConsoleScript25$_run_closure1@173a30bd}
Got a
Got R
Got TIM
正如所料......
根据具体情况,我倾向于避免这样做,因为匿名类路线更具可读性; - )
答案 2 :(得分:1)
你的匿名课应该没问题。由于您的所有方法都只委托给Appendable
的其他两个实例,您也可以像这样实现它:
final tee
tee = {
final... args
->
app1.append(*args)
app2.append(*args)
return tee
} as Appendable
*运算符使Groovy以#append
的内容作为参数调用args
。
你得到的MissingMethodException
是因为#consumeProcessOutput
有两个参数 - 一个用于STDOUT,一个用于STDERR。它也只能从输出中读取足够的数据以防止进程被阻塞,所以它可能不是你想要的。请改为#waitForProcessOutput
。
final app1 = new StringBuilder()
final app2 = new StringBuilder()
final tee
tee = {
final... args
->
app1.append(*args)
app2.append(*args)
return tee
} as Appendable
final cmd = 'ps a'
final p = cmd.execute()
p.waitForProcessOutput tee, tee
println '*' * 80
println app1
println '*' * 80
println app2
答案 3 :(得分:0)
这适用于最近的靛蓝:
List l=new LinkedList() {
{
add(new Integer(1));
add(new Integer(2));
}
};
println l