如何声明构造函数或扩展 groovy 脚本的 class?

How to declare a constructor or extends a class of a groovy script?

我正在为 Jenkins 开发 shared library,我想访问某些 class 之间的一些实用程序方法,但不是全部,因此我建立了一些声明:

这个 确实部分解决了我的问题,尽管存在序列化问题,但我注意到当我使用检查点并且从某个阶段恢复某些构建时,该实例会丢失所有额外的方法。

这个 本来可以帮助我解决序列化问题,但是作者似乎已经使用一种不是标题为的原始问题的方式解决了他的问题的根本原因。

有没有办法在不使用 class NameOfFile extends SomeOtherClass { put every thing inside this block } 语法的情况下扩展 groovy 中的隐式脚本 class?并且不使用 inner-class?

否则,有没有办法使用脚本 groovy 类似于上一个问题的语法来声明构造函数?

或者甚至,有没有办法更改序列化行为以在反序列化后再次安装额外的方法?

附录

脚本语法 more-or-less 如下所示:

考虑文件内容 src/cicd/pipeline/SomePipeline.groovy:

package cicd.pipeline

// there is no need to wrap everything inside class SomePipeline,
// since it is implicit

def method() {
  // instance method, here I can access pipeline steps freely
}

def static otherMethod() {
  // static method, here it is unable to access pipeline steps
  // without a instance
}

@groovy.transform.Field
def field

def call() {
  // if the class is used as method it will run
  this.method()
  SomePipeline.otherMethod() // or simply otherMethod() should work
  this.field = 'foo'
  println "this instance ${this.getClass().canonicalName} should be cicd.pipeline.SomePipeline"
}

// any code other than methods or variables with @Field
// annotation will be inside a implicit run method that is
// triggered likewise main method but isn't a static one
def localVar = 'foo'
println "It will not execute on constructor since it is on run: $localVar"
println "Method: ${org.codehaus.groovy.runtime.StackTraceUtils.sanitize(new Throwable()).stackTrace[0].methodName}"
println "this instance ${this.getClass().canonicalName} should be cicd.pipeline.SomePipeline"

如果我要使用 Java 冗长的语法,我必须将几乎所有内容都包装在 class SomePipeline 中,这在 groovy 中是隐含的,这就是我想要的脚本语法保留。

我意识到 this.getClass().superclass.canonicalName 当外部 Jenkins 管道是 groovy.lang.Script 并且当内部管道是 org.jenkinsci.plugins.workflow.cps.CpsScript 并且基于 this resource 我能够详细说明以下解决方案:

abstract class CustomScript extends org.jenkinsci.plugins.workflow.cps.CpsScript {
  public CustomScript() {
    // do something here, it will always execute regardless
    // serialization, and before everything
  }
}

@groovy.transform.BaseScript CustomScript baseScript

就是这样,按预期工作!当然你可以更好地阐述这个解决方案,以减少重复和避免inner-classes,但我会留给你想象。