如何在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
}
})
Run Code Online (Sandbox Code Playgroud)
我用这段代码得到一个例外:
Caught: groovy.lang.MissingMethodException: No signature of method: java.lang.UNIXProcess.consumeProcessOutput() is applicable for argument types: (MyClass$1) values: [MyClass$1@19c8ef56]
Run Code Online (Sandbox Code Playgroud)
这是一个棘手的情况,因为方法必须将对象本身作为一个返回Appendable,并且具有重载的方法名称,这对于groovy map到接口转换不能很好地工作.最简单,最清晰的方法可能是使用匿名内部类,就像在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" }
});
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用Expando带闭合的.这有点尴尬,因为每个方法名称只能在构造函数中初始化一个实现.请注意,省略的任何接口方法都会被赋予一个抛出异常的默认实现.
testAppendable(new Expando(
append: { char c ->
println "got $c"
delegate as Appendable
},
toString: { ->
"expando appendable"
}
) as Appendable)
Run Code Online (Sandbox Code Playgroud)
编辑:关于你的例子,我不明白为什么它会失败.我的测试几乎完全相同,没有任何问题.签名process.consumeProcessOutput看起来像什么?此外,您可以通过运行来仔细检查该MyClass$1实现.Appendablejavap MyClass$1
这适用于最近的靛蓝:
List l=new LinkedList() {
{
add(new Integer(1));
add(new Integer(2));
}
};
println l
Run Code Online (Sandbox Code Playgroud)