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".
CodePudding user response:
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.