Reputation: 1345
Is there in groovy similar feature to scala's implicit conversions?
I now that we can define custom type coercion like here: link, but there is need for 'as' keyword to add to use it.
To provide some concrete use case: I want to create conversion from String to Currency and after enabling it I want to pass String to method which requires Currency as a param.
public class SomeJavaClass {
void method(Currency currency){
...
}
}
and after implicit conversion this code should be valid:
class SomeGroovyClass {
def method(){
new SomeJavaClass().method("USD")
}
}
Is this somehow possible?
Upvotes: 0
Views: 275
Reputation: 2599
Groovy offers no implicit coercion, but dynamic features of the language allow to override methodMissing()
on the callee class (depending on whether the callee method is static, methodMissing()
or $static_methodMissing()
should be overridden, see 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)
}
}
where Currency
is e.g.
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")
}
}
Then the method invocations will yield the following results:
ShrewdCalculator.accept(Currency.US_DOLLAR) // --> US_DOLLAR
ShrewdCalculator.accept("USD") // --> US_DOLLAR thanks to fallback on methodMissing()
Another way is to add a coercion method to the ExpandoMetaClass
of the String
class and simply use Object
in the method signature only to coerce it manually under the hood:
class ShrewdCalculator {
static {
String.metaClass.asType(Currency) {
return Currency.valueOf(this)
}
}
static void accept(Object o) {
println o as Currency
}
}
In this case, the method will work like this:
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
Neither of these methods is akin to Scala's implicits, though.
Upvotes: 1