函数引用和 lambda

Function References and lambdas

我在尝试对 kotlin 使用 lambdas/函数引用时遇到编译错误:

class Foo {

    fun getFilteredList(){
        val numbers = listOf(1, 2, 3)
        numbers.filter(::isOdd) // prints [1, 3]
    }

    fun isOdd(x: Int): Boolean = x % 2 != 0

}

但是我收到一个编译时错误,指出类型不匹配:

Error:(18, 16) Gradle: Type inference failed: inline fun kotlin.Iterable.filter(predicate: (T) -> kotlin.Boolean): kotlin.List cannot be applied to receiver: kotlin.List arguments: (kotlin.reflect.KFunction2) Error:(18, 23) Gradle: Type mismatch: inferred type is kotlin.reflect.KFunction2 but (kotlin.Int) -> ??? was expected Error:(18, 23) Gradle: Type mismatch: inferred type is kotlin.reflect.KFunction2 but (kotlin.Int) -> kotlin.Boolean was expected Error:(18, 25) Gradle: Left-hand side of a callable reference with a receiver parameter cannot be empty. Please specify the type of the receiver before '::' explicitly

我不确定错误是什么,也不确定我应该在“::”之前明确指定什么类型

另一个问题: 我可以在 kotlin 中使用另一个对象函数作为参考吗?像这样:

class Bar {
    fun isOdd(x: Int): Boolean = x % 2 != 0
}

class Foo {

    fun getFilteredList(){
        val bar = Bar()
        val numbers = listOf(1, 2, 3)
        numbers.filter(bar::isOdd) // Use Bar's method
    }
}

这很有趣。 "Java strikes back"。哈哈

您的问题很简单:您在 class Foo 中声明了 isOdd,对吗?那么就不是函数,而是方法。这意味着它需要传入 Foo 的实例(this 引用)——这就是为什么它是 2 个参数的函数:Foo.(Int) -> Boolean。并且语法错误表明 - 对方法的引用看起来像 Foo::isOdd.

无论如何,即使在 Java 中,声明一个不使用对象的非静态方法也是一种反模式,你不同意吗?

可以通过声明一个没有 class 的自由函数或将其作为扩展来解决问题:fun Int.isOdd()

P.S。关于你的第二个问题 - 尚不支持该功能。

关于第二个例子:是的,自 Kotlin 1.1 起支持 bound function reference 语法,因此您可以像 Java.

一样编写 bar::isOdd

在第一个例子中,错误试图说 isOdd 实际上是两个参数(FooInt 类型)的函数,并传递一个函数不允许将两个参数作为参数,其类型是一个参数的函数。要使示例编译,您可以使 isOdd 成为顶级函数或局部函数,这将使它成为类型为 Int 的一个参数的函数。或者,如果您使用 Kotlin 1.1+,请使用绑定函数引用语法并简单地编写 this::isOdd.