在Groovy中是否有一种干净的方法指定Closure参数类型?

6

我知道@ClosureParams注释。但它似乎只涵盖更复杂的用例。我正在寻找像这里描述的“注释闭包”部分一样的东西。就像以下片段:

void doSomething(MyType src, @ClosureParams(MyType) Closure cl) { ... }

很不幸,这个示例在最新的Groovy版本中无法编译(我目前使用的是2.5.8版本)。我知道我可以通过以下方式来实现相同的效果:

void doSomething(MyType src, @ClosureParams(FirstParam) Closure cl) { ... }

尽管我的用例没有其他参数,但它本身就是一个闭包:

void doSomething(@ClosureParams(/* how? */) Closure cl) { ... }

我可以像这样黑掉它:

void doSomething(@ClosureParams(SecondParam) Closure cl, MyType ignore = null) { ... }

这远非干净,不是吗?

我也可以走:

void doSomething(@ClosureParams(value = SimpleType, options = ['com.somepackage.MyType']) Closure cl) { ... }

这种类型指定为字符串不仅难看且嘈杂,还会导致一些 IDE 功能无法使用。例如,重构重命名或搜索用法中的 MyType 将不会被捕获。

我想,没有更清晰的方法可以实现这一点,所以类型应该是作为类型指定的,而不是一个字符串,也不需要额外的不必要的参数,对吗?

像上面链接的博客文章中最初发布的那样,由 Cedric Champeau 发布的内容将是理想的选择。在我的情况下,它看起来像:

void doSomething(@ClosureParams(MyType) Closure cl) { ... }
1个回答

1
您可以考虑使用FromAbstractTypeMethods签名提示而不是SimpleType。使用它可能会比较繁琐,但它能够提供SimpleType提示类所缺少的好处-您可以轻松地重构在签名类中定义的类型,并且您可以查找在签名提示中使用的类的用法。主要缺点是,您需要为每个闭包签名提示创建一个额外的抽象类,并且包含签名作为抽象方法的类的名称必须被定义为常量字符串(SimpleType签名提示也存在同样的问题)。然而,您将获得一个单一参数doSomething方法,而无需添加第二个null参数,只是为了能够使用SecondParam签名提示。
package com.example

import groovy.transform.Immutable
import groovy.transform.stc.ClosureParams
import groovy.transform.stc.FromAbstractTypeMethods

class MyClass {
    static void doSomething(@ClosureParams(value = FromAbstractTypeMethods, options = ["com.example.MySignatures"]) Closure cl) {
        cl.call()
    }

    static void main(String[] args) {
        doSomething {
            println it.name
        }
    }
}

@Immutable
class MyType {
    String name
    int x
    int y
}

abstract class MySignatures {
    abstract void firstSignature(MyType myType)
    abstract void secondSignature(MyType myType, String str)
}

enter image description here

我猜测简单明了的@ClosureParams(String)变量已被移除,以满足其他更复杂的用例。 ClosureParams注释的API是固定的,并且将options限制为字符串数组。也许可以通过实现自己的ClosureSignatureHint来实现 - 我几个月前尝试过这样做,但我无法使IntelliJ IDEA使用我的自定义类提供签名提示。

谢谢Szymon!是的,我对@ClosureParams(String)被移除的猜测也类似。尽管如此,这很遗憾。我在另一个问题下看到了你的回复。虽然对于如此简单的事情来说,这是额外的冗余代码。我将重新考虑,但我想知道,为什么我甚至需要任何带有嘈杂选项的注释呢?声明MySignature为接口,只需调用doSomething { it.name }就足够了吗?由于Groovyness闭包被强制转换为接口实现,IDE也识别其参数类型? - topr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接