[英]How do I use an inner (nested) class created with a groovy AST transformation?
[英]How do I get something like an anonymous inner class in Groovy?
如何在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]
這是一個棘手的情況,因為方法必須將對象本身作為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
的簽名是什么樣的? 此外,您可以通過運行javap MyClass$1
來仔細檢查MyClass$1
實現了Appendable
。
作為除上述@ ataylor的解決方案 ,也可以使用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
正如所料......
根據情況,我傾向於避免這樣做,因為匿名類路線更具可讀性;-)
你的匿名課應該沒問題。 由於您的所有方法都只委托給另外兩個Appendable
實例,您也可以像這樣實現它:
final tee
tee = {
final... args
->
app1.append(*args)
app2.append(*args)
return tee
} as Appendable
*運算符使Groovy以args
的內容作為參數調用#append
。
你得到的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
這適用於最近的靛藍:
List l=new LinkedList() {
{
add(new Integer(1));
add(new Integer(2));
}
};
println l
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.