如果我想在一小段代码中使用Groovy类别,我通常会这样做
def foo() {
use(TimeCategory) {
new Date() + 5.hours
}
}
但是,如果我想在同一个班级的多个方法中使用某个类别,则必须在每个方法中重复调用use
,这很乏味。
有没有办法在班级应用类别?我尝试使用Groovy的@Mixin
注释,如下所示:
import groovy.time.*
@Mixin(TimeCategory)
class Foo {
Foo() {
new Date() + 5.hours
}
}
new Foo()
但是如果你在Groovy控制台中执行上面的代码,你会得到一个例外:
groovy.lang.MissingPropertyException:没有这样的属性:class for class:java.lang.Integer
答案 0 :(得分:0)
您可以在事后使用MetaClass.invokeMethod()
。它有点难看,但它保持了类代码相对干净:
import groovy.time.*
class Foo {
Foo() {
try { println (new Date() + 5.hours) }
catch (e) { println e }
try { println afterHours(5) }
catch (e) { println e }
}
Date tomorrow() {
new Date() + 1.days
}
Date nextWeek() {
new Date() + 7.days
}
Date afterHours(int h) {
new Date() + h.hours
}
}
解决方案#1:修改了下游某处的Foo.metaClass
,如下所示:
Foo.metaClass.invokeMethod = { String name, args ->
def metaMethod = Foo.metaClass.getMetaMethod(name, args)
def result
use(TimeCategory) {
result = metaMethod.invoke(delegate.delegate, args)
}
return result
}
按如下方式测试:
def foo = new Foo()
println "tomorrow: ${foo.tomorrow()}"
println "next week: ${foo.nextWeek()}"
println "after 7 hours: ${foo.afterHours(7)} "
产生以下结果
groovy.lang.MissingPropertyException: No such property: hours for class: java.lang.Integer
groovy.lang.MissingPropertyException: No such property: hours for class: java.lang.Integer
tomorrow: Fri Oct 17 14:46:52 CDT 2014
next week: Thu Oct 23 14:46:52 CDT 2014
after 7 hours: Thu Oct 16 21:46:52 CDT 2014
因此它不会在构造函数中或通过构造函数工作,但它可以在其他任何地方工作。
<小时/> 如果您不介意全局更改整数和日期的行为,则可以使用以下解决方案。
解决方案#2:
使用与以前相同的课程,而不是修改Foo.metaClass
,修改Integer.metaclass
和Date.metaClass
,如下所示:
Integer.metaClass.mixin TimeCategory
Date.metaClass.mixin TimeCategory
现在与之前相同的测试产生以下输出:
Thu Oct 16 21:19:24 CDT 2014
Thu Oct 16 21:19:24 CDT 2014
tomorrow: Fri Oct 17 16:19:24 CDT 2014
next week: Thu Oct 23 16:19:24 CDT 2014
after 7 hours: Thu Oct 16 23:19:24 CDT 2014