Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Groovy 在类级别应用类别_Groovy - Fatal编程技术网

Groovy 在类级别应用类别

Groovy 在类级别应用类别,groovy,Groovy,如果我想在一小段代码中使用Groovy类别,我通常会这样做 def foo() { use(TimeCategory) { new Date() + 5.hours } } 但是,如果我想在同一类的多个方法中使用一个类别,那么在每个方法中重复调用use是很麻烦的 有没有办法在班级级别应用类别?我尝试使用Groovy的@Mixin注释,如下所示: import groovy.time.* @Mixin(TimeCategory) class Foo { Foo() {

如果我想在一小段代码中使用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:无此类属性:类的小时数:java.lang.Integer


您可以在事后使用元类.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)} "
Integer.metaClass.mixin TimeCategory
Date.metaClass.mixin TimeCategory
测试如下:

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)} "
Integer.metaClass.mixin TimeCategory
Date.metaClass.mixin TimeCategory
结果如下

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 
所以它不在构造函数中工作,也不通过构造函数工作,但它在其他任何地方都可以工作。
如果您不介意全局更改Integer和Date的行为,那么您可以使用以下解决方案

解决方案#2:

使用与以前相同的类,而不是修改
Foo.metaClass
,而是修改
Integer.metaClass
Date.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)} "
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 

一个
@WithCategory
AST会很好。解决方案#2将使
TImeCategory
在全球范围内可用,但我正在寻找的是一种将其范围扩大到单个class@D诺尔,明白了。我想可能是这样的。