簡體   English   中英

我如何在Groovy中獲得類似匿名內部類的東西?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM