Inheritance groovy中具有超类参数的TupleConstructor

Inheritance groovy中具有超类参数的TupleConstructor,inheritance,groovy,constructor,annotations,Inheritance,Groovy,Constructor,Annotations,我的代码中有以下代码模式 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

我的代码中有以下代码模式

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编写构造函数)? ​
//您可以在上尝试代码,例如

您应该避免手动实现构造函数并同时使用AST转换生成构造函数的情况。您不应该将
@TupleConstructor
@InheritConstructor
混合使用。最新的(Groovy 2.4.12)类Javadoc非常神秘,它说:

(…)不要与一起使用

如果您选中继承构造函数,您将看到:

(…)不要与一起使用

Javadoc for Groovy2.5.0-SNAPSHOT在“已知限制”一节中介绍了更多内容:

已知的限制:
  • 如果您正在定义自己的构造函数或与创建构造函数的其他AST变换(例如,
    @inheritarconstructors
    )相结合,则此AST变换可能会成为不可操作的;在这种情况下,处理特定变换的顺序变得非常重要。有关自定义此行为的详细信息,请参见“力”属性
  • 此AST转换通常使用默认参数值,这会在封面下创建多个构造函数。如果您正在定义自己的构造函数或与创建构造函数的其他AST转换相结合(例如
    @inheritarconstructors
    ),则应小心使用;在这种情况下,处理特定变换的顺序变得非常重要。有关自定义此行为的详细信息,请参见defaults属性
  • 如果第一个属性(或字段)的类型为
    LinkedHashMap
    ,或者只有一个map、AbstractMap或HashMap属性(或字段),Groovy的普通映射样式命名约定将不可用
资料来源:

根据这些信息,您可以尝试实现预期行为的方法是摆脱手工编写的构造函数,并对层次结构中的所有类使用
@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
    初始化的缺少的构造函数

希望有帮助。

谢谢你的回答。您可以忽略@Inheritators构造函数。这不重要,我可以删除它。但我仍然得到了没有它的错误。我的问题是,您可以将类A视为库中的代码。我不想改变A的定义。我可以在B和C中应用变化。@GeorgeKastrinis谢谢你的解释。我已经更新了答案以符合此要求。希望能有帮助。