为什么要在Kotlin中将函数类型实现为接口

时间:2019-12-05 04:35:35

标签: kotlin interface kotlin-function-type

我偶然发现了一些东西,一直想知道为什么要这么做。

您可以通过简单的函数类型在Kotlin中实现接口:

"It is possible for a class to implement a function type as if it were an interface. It must then supply an operator function called invoke with the given signature, and instances of that class may then be assigned to a variable of that function type:"

class Divider : (Int, Int) -> Double {
    override fun invoke(numerator: Int, denominator: Int): Double = ...
}

但是我为什么要这样做?为什么要以这种方式添加接口?我认为只能添加一个功能而不能添加更多功能。 还是我可以使用函数主体而不是像正常接口中那样仅使用函数头来实现一个函数是一个优势吗?我认为在Java中可以向具有函数体的接口添加默认方法。所以也许是这样吗?

2 个答案:

答案 0 :(得分:1)

函数作为类可以具有状态。例如,您可以存储上一次调用并将历史记录用作缓存:

class Divider : (Int, Int) -> Double {
    val history = mutableMapOf<Pair<Int, Int>, Double>()

    override fun invoke(numerator: Int, denominator: Int): Double {
        return history.computeIfAbsent(Pair(numerator, denominator)) {
            numerator.toDouble() / denominator.toDouble()
        }
    }
}

fun main() {
    val divider = Divider()
    println(divider(1,2))
    println(divider(2,3))
    println(divider.history)
}

答案 1 :(得分:0)

编写实现函数类型接口的类可能不是很有用;但是,编写一个可以代替其他功能使用的类可能是有用的。

标准库中的一个示例是KProperty1接口。您可以编写如下代码:

data class C(val id: Int, val name: String)
val objs = listOf(C(1, "name1"), C(2, "name2"), C(3, "name3"))
val ids = objs.map(C::id)

在这里,C::id是类型KProperty1<C, Int>的属性引用,它可以用作List.map的参数来代替lambda,因为KProperty1<C, Int>扩展了{{ 1}}。但是,(C) -> Int除了作为函数传递外还有很多其他用途。