我按照 SonarLint 建议将一些只有一个函数的接口转换为 SAM,但由于函数参数中有默认值而出现问题。
fun interface HomeListener {
fun setSubTitle(subtitle: String = DEFAULT_VALUE_STRING)
}
我想知道这里出了什么问题,或者这是 Kotlin 和 JVM 之间的限制? JetBrain 的问题追踪中已经有一个 Bug 报告,但自 2021 年以来没有更新?
按照我的理解,SAM的要点是,如果只有一个要实现的抽象方法,你可以只提供一个 lambda 让编译器使用它作为实现。通常,您请求对象的实现,而“用户”需要提供它,并且可以选择仅提供 lambda 来实现。这对应于直接 lambda 参数:
fun doStuff(onSubtitleChange: (String) -> Unit) {
...
onSubtitleChange("foo")
...
}
这意味着在您的情况下,
setSubTitle
并不意味着由“用户”调用,而是由您调用,因此它不需要外部接口。就像使用 lambda 参数一样,您不会这样做(这当然是错误的语法):
fun doStuff(onSubtitleChange: (String = DEFAULT_VALUE_STRING) -> Unit) {
...
if (processedString != null)
onSubtitleChange(processedString)
else
onSubtitleChange()
...
}
但是你会这样做,这样会更清晰、更有意义:
fun doStuff(onSubtitleChange: (String) -> Unit) {
...
onSubtitleChange(processedString ?: DEFAULT_VALUE_STRING)
...
}
所以在我看来,拥有默认参数是没有意义的。而是像这样提供它:
fun doStuff(listener: HomeListener) {
...
listener.setSubtitle(processedString ?: DEFAULT_VALUE_STRING)
...
}