Java8高阶函数和Kotlin Lambdas互操作性

问题描述 投票:2回答:2

我有一个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存在兼容性问题,但我并不是最熟悉它们的。错误是:

enter image description here

问题是:是否有可能在Kotlin中覆盖此示例中的外部Java库的fitness()方法,如果是这样的话?

kotlin functional-interface
2个回答
3
投票

问题:

你回来了(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()
        }
    }
}

1
投票

将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有自己的那个名字

© www.soinside.com 2019 - 2024. All rights reserved.