函数引用和 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
实际上是两个参数(Foo
和 Int
类型)的函数,并传递一个函数不允许将两个参数作为参数,其类型是一个参数的函数。要使示例编译,您可以使 isOdd
成为顶级函数或局部函数,这将使它成为类型为 Int
的一个参数的函数。或者,如果您使用 Kotlin 1.1+,请使用绑定函数引用语法并简单地编写 this::isOdd
.
我在尝试对 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
实际上是两个参数(Foo
和 Int
类型)的函数,并传递一个函数不允许将两个参数作为参数,其类型是一个参数的函数。要使示例编译,您可以使 isOdd
成为顶级函数或局部函数,这将使它成为类型为 Int
的一个参数的函数。或者,如果您使用 Kotlin 1.1+,请使用绑定函数引用语法并简单地编写 this::isOdd
.