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_Metaclass_Mop_Expandometaclass - Fatal编程技术网

什么';在Groovy中使用可重用的元类代码是一种优雅的方式吗?

什么';在Groovy中使用可重用的元类代码是一种优雅的方式吗?,groovy,metaclass,mop,expandometaclass,Groovy,Metaclass,Mop,Expandometaclass,我想对我的一些类应用元编程转换,比如添加printXxx方法,如下所示: class Person { String name } def p = new Person() p.printName() // does something 一旦我有了一个元类,我大致知道如何做到这一点: Person.metaClass.methodMissing = { name, args -> delegate.metaClass."$name" = { println delegate."

我想对我的一些类应用元编程转换,比如添加printXxx方法,如下所示:

class Person {
  String name
}

def p = new Person()
p.printName() // does something
一旦我有了一个元类,我大致知道如何做到这一点:

Person.metaClass.methodMissing = { name, args ->
  delegate.metaClass."$name" = { println delegate."${getPropName(name)}" }
  delegate."$name"(*args)
}
现在,我如何将此代码转换为可重用的“库”?我想做一些类似的事情:

@HasMagicPrinterMethod
class Person {
  String name
}


定义要添加为特征的行为

trait MagicPrinter {                           
  void printProperties() {  
    this.properties.each { key, val ->
      println "$key = $val"
    }
  }          
}
然后将此特性添加到类中

class Person implements MagicPrinter {
  String name
}
现在使用它

new Person(name: 'bob').printProperties()

您可以采用混合方式:

class AutoPrint {
    static def methodMissing(obj, String method, args) {
        if (method.startsWith("print")) {
            def property = (method - "print").with { 
                it[0].toLowerCase() + it[1..-1] 
            }
            "${obj.getClass().simpleName} ${obj[property]}"
        }
        else {
            throw new NoSuchMethodException()
        }
    }
}
您可以将其与静态块混合使用:

class Person {
    static { Person.metaClass.mixin AutoPrint }
    String name
}

def p = new Person(name: "john doe")


try {
    p.captain()
    assert false, "should've failed"
} catch (e) {
    assert true
}

assert p.printName() == "Person john doe"
或使用expandoMetaClass:

class Car {
    String model
}

Car.metaClass.mixin AutoPrint

assert new Car(model: "GT").printModel() == "Car GT"

因为7个月后是新的“现在”:-)

我使用联合编译,在这样的设置下无法让traits工作(生成的存根文件无效)。另外,我不需要一个方法(printProperties),我希望为每个属性(printName、printAge等)动态生成一个方法
class Car {
    String model
}

Car.metaClass.mixin AutoPrint

assert new Car(model: "GT").printModel() == "Car GT"