【问题标题】:Closure with typed arguments in GroovyGroovy 中带有类型参数的闭包
【发布时间】:2011-08-06 14:22:53
【问题描述】:

我想更明确地说明我的闭包参数类型。所以我会写一些类似的东西

List<Y> myCollect(List<X> list, Closure<X,Y> clos) { ... }

我知道 Groovy 不会使用该类型信息,但 Groovy++ 可能会在编译时使用它。这可以实现吗(除了放在评论中)?

更新: 标题听起来可能会产生误导,但我认为上面的例子会更清楚。我有兴趣指定闭包的类型,它是某个函数的参数。假设,我想重新定义内置的collect。所以我有兴趣写myCollect,而不是写clos。我想要实现的是编译时错误

myCollect(['a', 'ab'], { it / 2 }) // compile error
myCollect(['a', 'ab'], { it.size() })  // OK 

【问题讨论】:

  • 在闭包类型中,V代表闭包的返回值,而不是它的参数。因此,有一个 Closure 是没有意义的,因为你不能返回两个值。
  • 我的意思是Closure&lt;X,Y&gt; 接受单个X 作为输入并返回Y。所以它可以应用于List&lt;X&gt;的项目。我更新了函数的返回类型。
  • 现在接受的答案应该是来自 Richard Vowles 的答案:stackoverflow.com/a/23887505/1915920,因为它涉及到闭包接口/函数的重新定义和相关的类型检查。

标签: groovy closures static-typing groovy++


【解决方案1】:

您可以定义闭包参数的类型,但上面显示的语法不正确。这是一个没有参数类型的闭包:

def concatenate = {arg1, arg2 ->
  return arg1 + arg2
}

这里是与参数类型相同的闭包

def concatenate = {String arg1, String arg2 ->
  return arg1 + arg2
}

我知道 Groovy 不会使用该类型信息,但 Groovy++ 可能会在编译时使用它。

Groovy 确实会进行一些编译时类型检查,但不如 Groovy++(或 Java)。即使在编译时不使用类型信息,它也会在运行时检查,并且作为一种文档形式也很有价值。

【讨论】:

  • 请看我的更新。你的concatenate是什么类型的?是Closure&lt;String,String,String&gt;吗?还是什么?
  • 我接受这个答案不是因为我对此感到满意,但这是唯一的一个:(也许,我的问题不够清楚。
【解决方案2】:

我认为您不再使用 Groovy++,但即使您使用,这也可能有效。它当然适用于静态类型的 Groovy 2.x

interface Z {
  void callback(X x, Y y)
}

List<Y> myCollect(List<X> list, Z clos) { 
  ... 

  clos.callback(x, y)
}

调用者然后用正常调用它:

List<Y> object.myConnect(list) { X x, Y y -> 
}

如果您遗漏了一个参数并使用了@CompileStatic,编译器会拾取丢失的参数或错误的类型。

这是可行的,因为 1 方法接口相当于 Groovy 中的闭包。

【讨论】:

  • 它也可以使用 Java 的函数式接口作为参数的类型,例如 Function (one-arg, one-return-value), BiFunction (two-args, one-return -value) 或Consumer(单参数,无返回值)。
猜你喜欢
  • 2012-09-16
  • 2014-08-09
  • 2019-06-23
  • 2022-07-27
  • 2019-11-13
  • 1970-01-01
  • 2016-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多