2011-10-25 35 views
6

如何在Groovy中定義一個匿名內部類?我看到了他們應該在Groovy 1.7中支持的參考,並且我使用了1.8。我如何在Groovy中獲得類似匿名內部類的東西?

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: [[email protected]] 
+0

以及什麼類型的消耗處理輸出要求?它是Appendable接口嗎? –

+0

描述你的問題的術語被稱爲「封閉」,我認爲... – djangofan

+0

它接受Appendable和OutputStream – dromodel

回答

0

這部作品在最近的靛藍:

List l=new LinkedList() { 
      { 
       add(new Integer(1)); 
       add(new Integer(2)); 
      } 
     }; 
println l 
6

這是一個棘手的情況,因爲方法必須返回對象本身作爲一個Appendable,並且有一個重載的方法名稱,它不適用於Groovy映射到接口強制轉換。最簡單,最清晰的方法可能就是使用匿名內部類,就像在Java中一樣。這需要常規(我覺得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

+0

+1添加了一個[可能的解決方案,使用Map來完成](http://stackoverflow.com/questions/7895545/how-do-i-get-something-like-an-anonymous-inner-class-in- groovy/7900626#7900626),但如果給出選擇,我會走你的路線;-) –

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") 
} 

我們可以構建我們的append因此:

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 = {[email protected]} 
Got a 
Got R 
Got TIM 

預期...

根據不同的情況,我會傾向於避免,雖然做這種方式,因爲匿名類路線是更具可讀性; - )

1

你的匿名類應該沒問題。由於所有的方法只是委託的其他Appendable兩個實例,你也可以實現這樣的:

final tee 
tee = { 
    final... args 
-> 
    app1.append(*args) 
    app2.append(*args) 

    return tee 
} as Appendable 

*運算引起的Groovy調用#appendargs作爲參數的內容。

您得到的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