【问题标题】:How do I get something like an anonymous inner class in Groovy?如何在 Groovy 中获得类似匿名内部类的东西?
【发布时间】:2011-10-25 20:36:30
【问题描述】:

如何在 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]

【问题讨论】:

  • 那么consumeProcessOutput 需要什么类型?是 Appendable 接口吗?
  • 我认为描述您的问题的术语称为“关闭”...
  • 它接受 Appendable 和 OutputStream
  • 在这种情况下闭包如何工作?
  • 我发现了问题:正确的方法是consumeProcessOutputStream()。

标签: groovy


【解决方案1】:

这是一个棘手的情况,因为方法必须将对象本身作为Appendable 返回,并且具有重载的方法名称,不能很好地与 groovy 映射到接口转换一起使用。最简单、最清晰的方法可能是只使用匿名内部类,就像在 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

【讨论】:

【解决方案2】:

作为@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

果然……

根据情况,我倾向于避免这样做,因为匿名类路由更具可读性;-)

【讨论】:

    【解决方案3】:

    这适用于最近的靛蓝:

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

    【讨论】:

      【解决方案4】:

      你的匿名类应该没问题。由于您的所有方法都只是委托给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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-29
        • 2011-08-24
        • 2016-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-16
        相关资源
        最近更新 更多