Dón*_*nal 11 groovy constructor
默认情况下,每个Groovy类都有一个Map构造函数,例如
class Foo {
def a
def b
}
// this works
new Foo(a: '1', b: '2')
Run Code Online (Sandbox Code Playgroud)
但是,似乎只要添加自己的构造函数,此默认构造函数就不可用
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')
Run Code Online (Sandbox Code Playgroud)
是否可以添加自己的构造函数而不会丢失默认的地图构造函数?我尝试用类注释,@TupleConstructor但它没有任何区别.我意识到我可以自己添加地图构造函数,例如
public Foo(Map map) {
map?.each { k, v -> this[k] = v }
}
Run Code Online (Sandbox Code Playgroud)
虽然上面的构造函数与默认的映射构造函数不同,因为映射中没有类中相应属性的键将导致异常.
bdk*_*her 20
如果您使用的是Groovy 2.5或更高版本,则可以应用@MapConstructor 注释.
@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'
Run Code Online (Sandbox Code Playgroud)
如果您使用的是旧版本的Groovy,那么@InheritConstructors 注释可以用作替代@MapConstructor,但正如Arie指出的那样,如果您的类扩展了一些基类,请避免使用此方法; 如果基类缺少无参数构造函数,则无效.
Wil*_*ill 10
在编译时,Groovy的地图构造函数使用空构造函数和一堆setter(以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"
Run Code Online (Sandbox Code Playgroud)
添加一个无参数的ctor并调用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
Run Code Online (Sandbox Code Playgroud)