问题 在Groovy中使用类型参数关闭


我想更清楚地了解关于他们的论证类型的闭包。所以我会写一些类似的东西

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 

13044
2018-04-15 19:46


起源

在类型Closure <V>中,V表示闭包的返回值,而不是其参数。因此,有一个Closure <V,X>是没有意义的,因为你不能返回两个值。 - Nancy Deschênes
我的意思是 Closure<X,Y> 接受单身 X 作为输入和返回 Y。所以它可以应用于 List<X>。我更新了函数的返回类型。 - Adam Schmideg
现在接受的答案应该是Richard Vowles的答案: stackoverflow.com/a/23887505/1915920 因为它关于闭包接口/功能和相关类型检查的重新定义。 - Andreas Dietrich


答案:


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

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

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

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

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

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


8
2018-04-18 09:21



拜托,看看我的更新。你是什​​么类型的 concatenate?是吗 Closure<String,String,String>?或者是什么? - Adam Schmideg
我接受这个答案并不是因为我对此很满意,但这是唯一的答案:(也许,我的问题不够明确。 - Adam Schmideg


我认为你不再使用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中的闭包。


2
2018-05-27 10:52