我尝试在kotlin中使用lambdas / function引用时遇到编译错误:
class Foo {
fun getFilteredList(){
val numbers = listOf(1, 2, 3)
numbers.filter(::isOdd) // prints [1, 3]
}
fun isOdd(x: Int): Boolean = x % 2 != 0
}
但是我得到一个编译时错误,说类型不匹配:
错误:(18,16)Gradle:类型推断失败:内联乐趣 kotlin.Iterable.filter(谓词:(T) - > kotlin.Boolean): kotlin.List不能应用于receiver:kotlin.List 参数:(kotlin.reflect.KFunction2)错误:(18,23)Gradle:类型不匹配:推断类型 是kotlin.reflect.KFunction2但是 (kotlin.Int) - > ???预计错误:(18,23)Gradle:类型不匹配: 推断类型是kotlin.reflect.KFunction2但是(kotlin.Int) - > kotlin.Boolean是预料之中的 错误:(18,25)Gradle:带有a的可调用引用的左侧 接收器参数不能为空。请指定的类型 接收器之前' ::'明确地
我不确定错误是什么,也不确定我应该在' ::'
之前明确说明的类型另一个问题: 我可以在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
}
}
答案 0 :(得分:16)
关于第二个例子:是的,自Kotlin 1.1以来支持bound function reference语法,因此您可以像Java一样编写bar::isOdd
。
在第一个示例中,错误试图说isOdd
实际上是两个参数(类型Foo
和Int
)的函数,并且传递一个函数需要两个参数作为参数,其类型是一个参数的函数是不允许的。要使示例编译,您可以使isOdd
成为顶级函数或本地函数,这将使其成为Int
类型的一个参数的函数。或者,如果您使用Kotlin 1.1+,请使用绑定函数参考语法,只需编写this::isOdd
。
答案 1 :(得分:7)
这很有趣。 “Java反击”。哈哈
您的问题很简单:您在班级isOdd
中宣布了Foo
,对吧?那么它不是功能,而是方法。这意味着它需要传递Foo
的实例(this
引用) - 这就是为什么它是2个参数的函数:Foo.(Int) -> Boolean
。语法错误显示 - 对方法的引用类似于Foo::isOdd
。
无论如何,声明一个不使用该对象的非静态方法即使在Java中也是反模式,你不同意吗?
可以通过声明没有类的自由函数或将其作为扩展来解决问题:fun Int.isOdd()
P.S。关于你的第二个问题 - 该功能尚不支持。