我有一个Java示例,其中实现方法
@Override
public Function<ISeq<Item>, Double> fitness() {
return items -> {
final Item sum = items.stream().collect(Item.toSum());
return sum._size <= _knapsackSize ? sum._value : 0;
};
}
IntelliJ将其自动翻译为Kotlin
override fun fitness(): Function<ISeq<Item>, Double> {
return { items:ISeq<Item> ->
val sum = items.stream().collect(Item.toSum())
if (sum.size <= _knapsackSize) sum.value else 0.0
}
}
(我将项目类型显式更改为0.0)
我仍然看到Java的功能和Kotlin本地lambda存在兼容性问题,但我并不是最熟悉它们的。错误是:
问题是:是否有可能在Kotlin中覆盖此示例中的外部Java库的fitness()方法,如果是这样的话?
问题:
你回来了(Kotlin)lambda ISeq<Knapsack.Item> -> Double
。但这不是你想要的。你想要返回一个Java Function<ISeq<Knapsack.Item>, Double>
。
解:
你可以使用SAM Conversion来创建一个Function
。
就像Java 8一样,Kotlin支持SAM转换。这意味着只要接口方法的参数类型与Kotlin函数的参数类型匹配,Kotlin函数文字就可以使用单个非默认方法自动转换为Java接口的实现。
我创建了一个最小的例子来证明这一点。考虑你有一个像这样的Java类:
public class Foo {
public Function<String, Integer> getFunction() {
return item -> Integer.valueOf(item);
}
}
如果你想在Kotlin中覆盖getFunction
,你会这样做:
class Bar: Foo() {
override fun getFunction(): Function<String, Int> {
return Function {
it.toInt()
}
}
}
将lambda作为Java的功能接口返回时,必须使用显式的SAM构造函数:
override fun fitness(): Function<ISeq<Item>, Double> {
return Function { items:ISeq<Item> ->
val sum = items.stream().collect(Item.toSum())
if (sum.size <= _knapsackSize) sum.value else 0.0
}
}
另外不要忘记导入java.util.function.Function
,因为Kotlin有自己的那个名字