Добавление настраиваемого конструктора без потери конструктора карты по умолчанию
По умолчанию каждый класс 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 }
}
Хотя конструктор выше не идентичен конструктору карты по умолчанию, потому что ключ на карте, который не имеет соответствующего свойства в классе, вызовет исключение.
Ответы
Ответ 1
Вы можете использовать аннотацию @InheritConstructors
.
@groovy.transform.InheritConstructors
class Foo {
def a, b
Foo(Integer x) {
println 'my constructor was called'
}
}
// this works
new Foo(1)
def mappedFoo = new Foo(a: '1', b: '1')
assert mappedFoo.a == '1'
assert mappedFoo.b == '1'
Ответ 2
После компиляции конструктор карты Groovy преобразуется в создание объекта с использованием пустого конструктора плюс набор настроек (в стиле 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"
Ответ 3
Добавьте no-arg 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