1

我有一个相当复杂的问题。我目前正在为 ERP 系统开发一种基于 groovy 的脚本语言。“我的”脚本语言的功能和语法基于erp系统使用的已经存在的旧FO语言。

因此:我通过调用从 ERP 中获取值,当前选择的数据集在哪里以及h.fieldname我想要我的字段值的字段的名称。我得到例如字符串类型的字段值。我现在想要的是用一些基于“旧”语法的函数来扩展我检索到的这些字符串。hfieldname

// some samples
// get last 3 characters 
h.fieldname >> 3
// get first 4 characters
h.fieldname << 4
// should still work even if h.fieldname, returns something which extends String but is not a String
assert h.fieldname == "Foo"

更新

我试图利用@daggett的答案,这里是我的方法:

public abstract class BaseScript extends Script implements GroovyObject {
    
    @Override
    public Object run() {
        Object o = null;
        try {
            final ExpandoMetaClass metaClass = new ExpandoMetaClass(String.class, false, true);
            
            //Closure c = { int x-> delegate[-x..-1] };
            
            //ClosureMetaMethod foo = new ClosureMetaMethod​("rightShift ", c , doCall);
            
            
            metaClass.initialize();
            
            o = runCode();
        } catch (Exception e) {
            this.onerror(e);
        } finally {
            this.always();
        }
        return o;
    }

    public abstract Object runCode();

    public Object always() {
        return null;
    }
    
    public Object onerror(Object ex) {
        if (ex instanceof Exception) {
            Exception e = (Exception) ex;
            e.printStackTrace();
        }
        return null;
    }
    
}

但老实说,我不知道如何实现它,我也找不到任何例子。

更新 2 和解决方案

基于@daggett 的回答。

package groovy.runtime.metaclass.java.lang;

import groovy.lang.DelegatingMetaClass;
import groovy.lang.MetaClass;

public class StringMetaClass extends DelegatingMetaClass {

    public StringMetaClass(Class<?> theClass) {
        super(theClass);
    }

    public StringMetaClass(MetaClass metaClass) {
        super(metaClass);
    }

    @Override
    public Object invokeMethod(Object object, String name, Object[] args) {
        // implementiert "test" >> 3
        if (name.equals("rightShift")) {
            if (args.length == 1) {
                if (args[0] instanceof Integer) {
                    String str = object.toString();
                    int x = ((Integer) args[0]).intValue();
                    if (str.length() > x) {
                        return str.substring(str.length() - x);
                    }
                    return str;
                } else {
                    throw new IllegalArgumentException("wrong argument type, should be integer");
                }
            } else {
                throw new IllegalArgumentException("too many arguments");
            }
        }
        // implementiert "test" << 3
        if (name.equals("leftShift")) {
            if (args.length == 1) {
                if (args[0] instanceof Integer) {
                    String str = object.toString();
                    int x = ((Integer) args[0]).intValue();
                    if (str.length() > x) {
                        return str.substring(0,x);
                    }
                    return str;
                } else {
                    throw new IllegalArgumentException("wrong argument type, should be integer");
                }
            } else {
                throw new IllegalArgumentException("too many arguments");
            }
        }
        else {
            return super.invokeMethod(object, name, args);
        }
    }

}
4

1 回答 1

1

您不能扩展字符串类,因为它是最终的,但是在 groovy 中,您可以在元类的帮助下向字符串类添加新方法

String.metaClass.rightShift = { int x-> delegate[-x..-1] }

"1234567890" >> 3

返回

890

以同样的方式实现leftShift方法<<

最后一个请求 ( assert s1==s2) 不相关,因为 String 是最终类(不可扩展)

于 2020-08-27T14:55:14.377 回答