为什么在Kotlin中使用功能接口



我正在学习Kotlin,我在这里遇到了函数接口:https://kotlinlang.org/docs/fun-interfaces.html#sam-转换,并且我不太理解像示例中那样声明和使用接口的目的。示例如下:

fun interface IntPredicate {
fun accept(i: Int): Boolean
}
// Creating an instance of a class
val isEven = object : IntPredicate {
override fun accept(i: Int): Boolean {
return i % 2 == 0
}
}
// Or creating an instance using lambda
val isEven = IntPredicate { it % 2 == 0 }

fun main() {
println("Is 7 even? - ${isEven.accept(7)}")
}

既然我们可以声明一个函数isEven,然后随时调用它,为什么要这样做呢

fun isEven(i: Int): Boolean {
return i % 2 == 0
}
fun main() {
println("Is 7 even? - ${isEven(7)}")
}

我们得到了同样的结果。我想我遗漏了什么,有人能帮我解释一下吗。现在我知道lambda表达式是什么,但这些代码行到底做了什么(我以前在其他文件中见过,但不理解(

// Creating an instance of a class
val isEven = object : IntPredicate {
override fun accept(i: Int): Boolean {
return i % 2 == 0
}
}

谢谢!

您的问题实际上不是关于Kotlin和函数接口,而是关于面向对象编程的基本概念。你要问的问题是:如果我们只能使用普通的类/函数,为什么我们需要接口?它是对软件组件进行抽象;以解耦函数的调用方及其实现。

假设我们有一个函数,用来过滤一个整数列表。它不知道过滤规则,而是以IntPredicate的形式从外部代码中接收这些规则。可以声明为:

fun filterList(list: List<Int>, predicate: IntPredicate): List<Int> = TODO()
interface IntPredicate {
fun accept(i: Int): Boolean
}

因为我们必须提供IntPredicate的实现,所以使用此函数相当麻烦。对于每种使用,我们都需要IntPredicate的另一种实现。即使我们需要执行一个非常简单的过滤,比如寻找奇数。对于这样一个简单的案件来说,这似乎是一项艰巨的工作。

功能接口和SAM转换使此类情况更易于使用。在将谓词接口声明为fun interface IntPredicate之后,我们可以这样使用我们的函数:

filterList(list) { it % 2 == 0 }

现在,我们可以提供lambda,而不是实现整个类。

功能接口并不是全新的东西,它们不会让你做任何没有它们就不可能做的事情。通过将接口标记为fun,我们只是为该接口启用了一个有用的语法糖。

请注意,在实践中,我的例子没有太多意义。我们在stdlib中已经有一个非常相似的filter()函数,在Kotlin中,在这种情况下,我们通常更喜欢函数类型而不是接口。

最新更新