Groovy中的自定义隐式强制

时间:2019-04-30 14:20:34

标签: groovy

与scala的隐式转换有类似的特点吗?

我现在可以像下面这样定义自定义类型强制: link,但需要添加'as'关键字才能使用它。

要提供一些具体的用例:我想创建从String到Currency的转换,并启用它之后,我想将String传递给需要Currency作为参数的方法。

ViewerConfig config = new ViewerConfig();
config.StoragePath = "D:\\storage\\";

// Create handler
ViewerImageHandler imageHandler = new ViewerImageHandler(config);

// Guid implies that unique document name 
string guid = "sample.psd";

// Get document pages as images
List<PageImage> pages = imageHandler.GetPages(guid);

foreach (PageImage page in pages)
{
    // Access each image using page.Stream
}

,隐式转换后,此代码应有效:

public class SomeJavaClass { 
    void method(Currency currency){
    ...
    }
}

这有可能吗?

1 个答案:

答案 0 :(得分:0)

Groovy不提供隐式强制,但是语言的动态功能允许在被调用方类上覆盖methodMissing()(取决于被调用方方法是静态的,methodMissing()还是$static_methodMissing())已覆盖,请参见docs):

class ShrewdCalculator {
    static void accept(Currency o) {
        println o
    }

    static def $static_methodMissing(String name, def args) {
        if (name == "accept" && args.size() == 1 && args[0].class == String) {
            return accept(Currency.valueOf(args[0]))
        }
        throw new MissingMethodException(name, this.class, args)
    }
}

其中Currency

enum Currency {
    US_DOLLAR, EURO

    static valueOf(String s) {
        if (s == "USD") return US_DOLLAR
        if (s == "EUR") return EURO
        throw new RuntimeException("No currency defined for input $s")
    }
}

然后方法调用将产生以下结果:

ShrewdCalculator.accept(Currency.US_DOLLAR) // --> US_DOLLAR
ShrewdCalculator.accept("USD") // --> US_DOLLAR thanks to fallback on methodMissing()

另一种方法是将强制方法添加到ExpandoMetaClass类的String并仅在方法签名中使用Object只是为了在幕后手动强制它:

class ShrewdCalculator {
    static {
        String.metaClass.asType(Currency) {
            return Currency.valueOf(this)
        }
    }

    static void accept(Object o) {
        println o as Currency
    }
}

在这种情况下,该方法将像这样工作:

ShrewdCalculator.accept(Currency.US_DOLLAR) // --> US_DOLLAR because Currency as Currency is no-op
ShrewdCalculator.accept("USD") // --> US_DOLLAR thanks to coercion defined in String's metaclass

但这两种方法都不类似于Scala的隐式。