什么';在Groovy中使用可重用的元类代码是一种优雅的方式吗?
我想对我的一些类应用元编程转换,比如添加printXxx方法,如下所示:什么';在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."
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"