我的代码中有以下代码模式
class A {
String x
String y
String z
A() { }
A(String a) { }
}
@groovy.transform.InheritConstructors
class B extends A {
B(String x, String y) {
this.x = x
this.y = y
this.z = ""
}
}
@groovy.transform.TupleConstructor(callSuper = true, includeSuperProperties = true)
class C extends B {
String r
}
println new B("x1", "y1").x
println new C("x2", "y2", "r").r
我尝试实现的是能够像最后一行一样创建C
对象。我得到的是一个错误。
Could not find matching constructor for: B(java.lang.String, java.lang.String, java.lang.String)
有没有办法通过注释实现这一点(避免在C中自己编写构造函数)? //您可以尝试使用https://groovy-playground.appspot.com/上的代码
答案 0 :(得分:1)
您应该避免手动实现构造函数并同时使用AST转换生成的情况。您也不应将@TupleConstructor
与@InheritConstructor
混在一起。最新的(Groovy 2.4.12)TupleConstructor
类Javadoc非常神秘,它说:
(...)不要与
InheritConstructors
一起使用。
如果你检查InheritConstructors
Javadoc,你会看到:
(...)不要与
TupleConstructor
一起使用。
用于Groovy的Javadoc 2.5.0-SNAPSHOT 在“已知限制”部分中说了更多内容:
已知限制:
- 如果您定义自己的构造函数或与创建构造函数的其他AST变换(例如
@InheritConstructors
)组合,则此AST变换可能会变为无操作;在这种情况下,处理特定变换的顺序变得很重要。有关自定义此行为的详细信息,请参阅force属性。- 此AST转换通常使用默认参数值,这些值在封面下创建多个构造函数。如果要定义自己的构造函数或与创建构造函数的其他AST转换组合(例如
@InheritConstructors
),则应小心使用;在这种情况下,处理特定变换的顺序变得很重要。有关自定义此行为的详细信息,请参阅defaults属性。- 如果第一个属性(或字段)具有类型
,则Groovy的常规地图样式命名约定将不可用LinkedHashMap
或者存在单个Map,AbstractMap或HashMap属性(或字段)来源:http://docs.groovy-lang.org/next/html/gapi/groovy/transform/TupleConstructor.html
根据这些信息,您可以尝试实现预期行为的方法是摆脱手写的构造函数,并使用@TupleConstructor
代替层次结构中的所有类,例如。
import groovy.transform.TupleConstructor
@TupleConstructor
class A {
String x
String y
String z
}
@TupleConstructor(callSuper = true, includeSuperProperties = true)
class B extends A {
}
@TupleConstructor(callSuper = true, includeSuperProperties = true)
class C extends B {
String r
}
println new B("x1", "y1").x
println new C("x2", "y2", "r").r
编辑:如果修改类A
不是一个选项,那么您可以通过遵循类层次结构来实现此目的:
import groovy.transform.TupleConstructor
class A {
String x
String y
String z
A() { }
A(String a) { }
}
@TupleConstructor(includeSuperProperties = true)
class B extends A {
}
@TupleConstructor(callSuper = true, includeSuperProperties = true)
class C extends B {
String r
}
println new C("x2", "y2", "z2", "r2").dump()
运行以下脚本将返回输出:
<C@670002 r=r2 x=x2 y=y2 z=z2>
这里发生的是:
A
未更改。B
为从A
C
添加了缺少构造函数,以满足字段r
的初始化。我希望它有所帮助。