如何动态地将一个类的所有方法添加到另一个类中 [英] How to dynamically add all methods of a class into another class

查看:100
本文介绍了如何动态地将一个类的所有方法添加到另一个类中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Jenkins上有一个全局共享库隐式加载到所有管道上,那么我的Jenkinsfile就像这样:

I have a global shared library on Jenkins implicitly loaded on all pipelines, then my Jenkinsfile is like that:

new com.company.Pipeline()()

然后共享库在目录src/com/company上的Pipeline.groovy类下面有一些文件:

And then the shared library has on directory src/com/company some files, below the Pipeline.groovy class:

package com.company  

import static Utils.*

def call() {
  // some stuff here...
}

问题是,这样我必须静态声明所有方法,因此如果没有Pipeline类的实例,我将失去上下文并且无法轻松访问jenkins的方法.如您所见,在此处,他们将this传递给方法mvn.

The problem is, this way I have to static declare all methods, thus I lose the context and cannot access jenkins' methods easly without the Pipeline class' instance. As you can see here they passing this to the method mvn.

想避免这种情况,我想知道通过调用Utils.install this而不是使用import static Utils.*动态地将所有方法添加为闭包,然后我的Utils.groovy就是这样:

Thinking of avoid this I was wondering about dynamically add all methods as closures by calling Utils.install this instead of using import static Utils.*, then my Utils.groovy is something like that:

package com.company

private Utils() {}

static def install(def instance) {
  def utils = new Utils()
  // Some extra check needed here I know, but it is not the problem now
  for (def method in (utils.metaClass.methods*.name as Set) - (instance.metaClass.methods*.name as Set)) {
    def closure = utils.&"$method"
    closure.delegate = instance
    instance.metaClass."$method" = closure
  }
}

def someMethod() {
  // here I want to use sh(), tool(), and other stuff freely.
}

但是它引发了GStringImpl无法转换为String的错误,我相信.&不适用于变量,如何将方法转换为在变量上具有方法名称的闭包?我的 MetaMethod 主要是 CachedMethod 例如,如果有可能将其设为

But it raises an GStringImpl cannot be cast to String error, I believe .& do not work with variables, how can I convert a method into closure having the method name on a variable? I have the MetaMethod mostly being a CachedMethod instance, if it were possible to turn it a ClosureMetaMethod instance maybe the problem can be solved, but whenever I search for method to closure conversion for groovy I just found the .& solution!

如果我使用instance.metaClass.someMethod = utils.&someMethod,它确实可以工作,但是我希望它像动态的一样,因为我添加了新方法而不必担心共享它.

If I use instance.metaClass.someMethod = utils.&someMethod it do work, but I want it to be dinamic as I add new methods without needing to worry about sharing it.

推荐答案

有一种方法可以动态地做到这一点.表示法utils.&someMethod返回 MethodClosure 对象,可以使用其构造函数简单地实例化:

There is a way to do it dynamically. Notation utils.&someMethod returns a MethodClosure object that can be simply instantiated with its constructor:

MethodClosure(Object owner, String method)

考虑以下示例:

class Utils {
    def foo() {
        println "Hello, Foo!"
    }
    def bar() {
        println "Hello, Bar!"
    }
}

class Consumer {
}

def instance = new Consumer()
def utils = new Utils()

(utils.metaClass.methods*.name - instance.metaClass.methods*.name).each { method ->
    def closure = new MethodClosure(utils, method)
    closure.delegate = instance
    instance.metaClass."$method" = closure
}

instance.foo() // Prints "Hello, Foo!"
instance.bar() // Prints "Hello, Bar!"

在此示例中,我使用def closure = new MethodClosure(utils, method)获取对象方法引用,然后将此方法添加到instance对象.希望对您有帮助.

In this example I use def closure = new MethodClosure(utils, method) to get object method reference and then add this method to instance object. I hope it helps.

这篇关于如何动态地将一个类的所有方法添加到另一个类中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆