在类的所有实例方法中隐式使用 Groovy Category

Posted

技术标签:

【中文标题】在类的所有实例方法中隐式使用 Groovy Category【英文标题】:Use Groovy Category implicitly in all instance methods of class 【发布时间】:2011-07-29 23:02:06 【问题描述】:

我有一个简单的 Groovy 类别类,它向 String 实例添加方法:

final class SampleCategory 

    static String withBraces(String self) 
        "($self)"
    


我想在我的单元测试中使用这个类别(例如)。它看起来像这样:

class MyTest 
    @Test
    void shouldDoThis() 
        use (SampleCategory) 
            assert 'this'.withBraces() == '(this)'
        
    

    @Test
    void shouldDoThat() 
        use (SampleCategory) 
            assert 'that'.withBraces() == '(that)'
        
    

然而,我想要实现的是能够指定 SampleCategory 类别在 MyTest 的每个实例方法的范围内使用,因此我不必在每个方法中指定 use(SampleCategory) ... .

有可能吗?

【问题讨论】:

应该可以使用 AST 转换,但不知道如何实现它。用户指南here 中有一个部分,Hamlet D'arcy 在他的"Code generation on the JVM"-talk 中谈到了它(不确定他有多深入)。祝你好运! 谢谢你的想法!听起来像是一个不错的小型 OSS 项目候选人 :) 【参考方案1】:

您可以使用 mixin 将类别直接应用于 String 的元类。将 null 分配给 metaClass 以将其重置为 groovy 默认值。例如:

@Before void setUp()  
    String.mixin(SampleCategory)


@After void tearDown() 
    String.metaClass = null


@Test
void shouldDoThat() 
    assert 'that'.withBraces() == '(that)'

【讨论】:

你真的试过了吗?我想出了一个几乎相同的解决方案,并对其进行了测试,但没有奏效。 ataylor,谢谢,解决方案确实有效,而且非常优雅!我做了几个小改动(例如使用@BeforeClass/@AfterClass) 太好了,我想有比进行自定义 AST 编程更简单的方法 :) 感谢您的提示!【参考方案2】:

现在您可以选择使用扩展模块而不是类别: http://mrhaki.blogspot.se/2013/01/groovy-goodness-adding-extra-methods.html

从好的方面来说,Intellij 会识别扩展。我刚刚注意到它甚至不需要是链接建议的单独模块,只需将 META-INF/services/org.codehaus.groovy.runtime.ExtensionModule 添加到项目中:

# File: src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
moduleName = module
moduleVersion = 1.0
extensionClasses = SampleExtension

扩展类的定义与普通类别非常相似:

class SampleExtension 
    static String withBraces(String self) 
        "($self)"
    

可以这样使用:

def "Sample extension"() 
    expect: 'this'.withBraces() == '(this)'

如果您使用的是 Spock,则可以在规范中使用 @Use 注释。这样做的缺点是 Intellij 无法识别它。

【讨论】:

以上是关于在类的所有实例方法中隐式使用 Groovy Category的主要内容,如果未能解决你的问题,请参考以下文章

scala中隐式转换之隐式类

scala中隐式转换之总结

scala中隐式转换之隐式转换调用类中本不存在的方法

为啥要在 Python 中隐式检查是不是为空? [关闭]

final详解

在 Maven 中隐式包含可选依赖项