默认情况下,每个Groovy类都有一个Map构造函数,例如
class Foo {
def a
def b
}
// this works
new Foo(a: '1', b: '2')
但是,似乎只要添加自己的构造函数,此默认构造函数就不可用
class Foo {
Foo(Integer x) {
println 'my constructor was called'
}
def a
def b
}
// this works
new Foo(1)
// now this doesn't work, I get the error: groovy.lang.GroovyRuntimeException:
// failed to invoke constructor
new Foo(a: '1', b: '2')
是否可以在不丢失默认地图构造函数的情况下添加自己的构造函数?我尝试使用@TupleConstructor
注释该类,但它没有任何区别。我意识到我可以自己添加地图构造函数,例如
public Foo(Map map) {
map?.each { k, v -> this[k] = v }
}
虽然上面的构造函数与默认的地图构造函数不同,因为地图中没有类中相应属性的键会导致异常。
答案 0 :(得分:20)
如果您使用的是Groovy 2.5或更高版本,则可以应用@MapConstructor
annotation。
@groovy.transform.MapConstructor
class Foo {
def a, b
Foo(Integer x) {
println 'my constructor was called'
}
}
// this works
new Foo(1)
// the map constructor is present, too
def mappedFoo = new Foo(a: '1', b: '1')
assert mappedFoo.a == '1'
assert mappedFoo.b == '1'
如果您使用的是较早版本的Groovy,@InheritConstructors
annotation可以替代@MapConstructor
,但正如Arie指出的那样,如果您使用你的课程扩展了一些基类;如果基类缺少无参数构造函数,则无效。
答案 1 :(得分:9)
编译后,Groovy的地图构造函数被转换为object creation using an empty constructor plus a bunch of setters(以javabean样式)。有一个空构造函数可以解决这个问题:
class Foo {
Foo(Integer x) {
println 'my constructor was called'
}
Foo() {}
def a
def b
}
new Foo(1)
foo = new Foo(a: '1', b: '2')
assert foo.a == "1"
答案 2 :(得分:4)
添加无法参与者并致电super
,例如,
class Foo {
Foo(Integer x) {
println 'my constructor was called'
}
Foo() { super() } // Or just Foo() {}
def a
def b
}
f = new Foo(a: '1', b: '2')
println f.a
=> 1