我正在学习Kotlin,我在功能方面遇到了一些麻烦。我正在尝试使用泛型参数创建类似功能的界面。在Java中我会创建这样的东西:
@FunctionalInterface
public interface Foo<T extends Bar> {
String something(T arg);
}
然后我可以在其他地方使用这个(假设Person
延伸Bar
:
Foo<Person> f = p -> p.toString();
你怎么用Kotlin写这个?
我尝试的第一件事是使用这样的类型别名:
typealias Foo<T> = (T) -> String
但是,当我将绑定添加到type参数时,它停止工作:
typealias Foo<T: Bar> = (T) -> String // Error: Bounds are not allowed on type alias parameters
第二种方法是编写扩展函数类型的接口:
interface Foo<T: Bar> : (T) -> String
但是,现在我不知道如何使用它来实例化lambda函数。当我像这样创建类时,它可以工作:
class Something: Foo<Person> {
override fun invoke(p: Person): String {
return p.toString()
}
}
val f = Something()
但这是一个很大的开销,我确信必须有一个更好的解决方案。
那么如何定义一个函数签名,可以被许多函数重用,这些函数支持带有kotlin边界的泛型参数?
大多数情况下(总是?),在接收它的函数的参数中定义lambda的类型就足够了。
例如:
open class Bar
class Person: Bar()
var f = { p: Person -> p.toString() }
fun <T : Bar> withFoo(block: (T) -> String) { }
fun <T : Bar> otherFoo(block: (T) -> String) { }
fun main() {
withFoo(f)
otherFoo(f)
}
与Kotlin文档相同的说法是:“由于Kotlin具有适当的函数类型,因此不需要将函数自动转换为Kotlin接口的实现,因此不受支持。”
见https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions