I define an enum that takes a method reference:
enum class Op(val param: (Expression<String>, String) -> Predicate) {
GREATER_THAN(CriteriaBuilder::greaterThan)
}
There are two candidates in the CriteriaBuilder class, and the compiler can't figure out which one I mean ("Overload resolution ambiguity. All these functions match."):
<Y extends Comparable<? super Y>> Predicate greaterThan(Expression<? extends Y> x, Expression<? extends Y> y);
<Y extends Comparable<? super Y>> Predicate greaterThan(Expression<? extends Y> x, Y y);
Why can't Kotlin infer the right type? Clearly the first method is not possible. I can't figure out how to guide the compiler, casting it to the right type doesn't seem to work:
GREATER_THAN(CriteriaBuilder::greaterThan as (Expression<String>, String) -> Predicate)
Compiler complains "Cannot choose among the following candidates without completing type inference".
Given the Javadoc of CriteriaBuilder, the method you're referring to is not static.
Since you're not providing an instance of CriteriaBuilder in your function reference, this means that CriteriaBuilder::greaterThan actually expects a receiver or parameter of type CriteriaBuilder in addition to the 2 arguments, which doesn't match the signature that you're expecting: (Expression<String>, String) -> Predicate.
If you want the caller of Op.param to provide the criteria builder instance, then I suggest to change Op.param's type to (CriteriaBuilder, Expression<String>, String) -> Predicate or CriteriaBuilder.(Expression<String>, String) -> Predicate - which would match the function reference CriteriaBuilder::greaterThan. The choice of which one to use depends on how you want to call it:
enum class Op(val param: CriteriaBuilder.(Expression<String>, String) -> Predicate) {
GREATER_THAN(CriteriaBuilder::greaterThan)
}
// or
enum class Op(val param: (CriteriaBuilder, Expression<String>, String) -> Predicate) {
GREATER_THAN(CriteriaBuilder::greaterThan)
}
If you want to have the CriteriaBuilder "built-in" the enum, you can instantiate it up front, and then use your specific instance in the function reference:
val yourCriteriaBuilder: CriteriaBuilder = TODO("create it somehow")
enum class Op(val param: (Expression<String>, String) -> Predicate) {
GREATER_THAN(yourCriteriaBuilder::greaterThan)
}
I'm not familiar with the CriteriaBuilder API, so I'm not sure if this last option is actually desirable. You might want new instances each time instead - your call.