我有以下Java代码:
public class DatabaseManager {
public interface Predicate<T> {
boolean test(T t);
}
private interface Consumer<T> {
void apply(T t);
}
private void updateLiveLists() {
updateLiveLists(liveList -> true);
}
private void updateLiveLists(Predicate<MutableLiveList<?>> predicate) {
forEachLiveList(liveList -> {
if (predicate.test(liveList)) {
refresh(liveList);
}
});
}
private void forEachLiveList(Consumer<MutableLiveList<?>> consumer) {
...
}
然后我在Android Studio中使用了Java -> Kotlin conversion
:
class DatabaseManager {
interface Predicate<T> {
fun test(t: T): Boolean
}
private interface Consumer<T> {
fun apply(t: T)
}
private fun updateLiveLists(predicate: Predicate<MutableLiveList<*>> = { liveList -> true }) {
forEachLiveList({ liveList ->
if (predicate.test(liveList)) {
refresh(liveList)
}
})
}
private fun forEachLiveList(consumer: Consumer<MutableLiveList<*>>) {
...
}
失败并显示以下错误:
类型不匹配
Required: DatabaseManager.Consumer<MutableLiveList<*>>
找到: (???) -> 单位
现在我必须将代码更改为以下内容:
private fun updateLiveLists(predicate: Predicate<MutableLiveList<*>> = object : Predicate<MutableLiveList<*>> {
override fun test(t: MutableLiveList<*>): Boolean {
return true;
}
}) {
forEachLiveList(object : DatabaseManager.Consumer<MutableLiveList<*>> { // <--- !!
override fun apply(t: MutableLiveList<*>) {
if (predicate.test(t)) {
refresh(t)
}
}
})
}
好的,所以我必须明确地将这个匿名接口声明为 object
的显式子类,因为无论出于何种原因 Kotlin 无法弄清楚 lambda。
如果有帮助,我在它下面的函数中遇到了同样的问题:
fun refresh(vararg tables: Table) {
updateLiveLists({ liveList ->
for (table in tables) {
if (liveList.getTable() === table) {
return@updateLiveLists true
}
}
false
})
}
其中说:
类型不匹配:
Required: DatabaseManager.Predicate<MutableLiveList<*>>
发现:??? ->布尔值
我必须这样做
fun refresh(vararg tables: Table) {
updateLiveLists(object: DatabaseManager.Predicate<MutableLiveList<*>> { // <--
override fun test(t: MutableLiveList<*>): Boolean {
for (table in tables) {
if (t.getTable() === table) {
return true
}
}
return false
}
})
}
为什么,我怎样才能避免这种情况?如何使用我自己的谓词/消费者,而不会让 Kotlin 对 lambda 类型感到困惑?
亏了/u/lupajz
我现在知道问题是 Kotlin 中定义的接口由于 https://discuss.kotlinlang.org/t/kotlin-and-sam-interface-with-two-parameters/293/5
基本上它归结为
"当你可以使用 Kotlin 的功能接口和类型别名时,你为什么要这样做;如果你需要这个,那么用Java定义接口"。
有几种解决方法:
1.) 内联对象(这是我上面作为问题的一部分展示的)
2.) 类型别名 + 公开重载方法
private typealias KotlinPredicate<T> = (T) -> Boolean;
private typealias KotlinConsumer<T> = (T) -> Unit;
class DatabaseManager {
private interface Consumer<T> {
fun apply(t : T) : Unit;
}
private fun forEachLiveList(consumer: Consumer<MutableLiveList<*>>) {
forEachLiveList({
consumer.apply(it)
})
}
private fun forEachLiveList(consumer: KotlinConsumer<MutableLiveList<*>>) {
...
}
和
interface Predicate<T> {
fun test(t : T) : Boolean;
}
fun updateLiveLists(predicate: Predicate<MutableLiveList<*>>) {
updateLiveLists({
predicate.test(it)
})
}
fun updateLiveLists(predicate: KotlinPredicate<MutableLiveList<*>> = { liveList -> true }) {
forEachLiveList({ liveList ->
if (predicate.invoke(liveList)) {
refresh(liveList)
}
})
}