我有以下方法
fun <P> configure(property: KProperty1<R, P>, transform: (source: S) -> P) {
...
}
如果我使用Foo::bar
调用此函数,其中::bar
不可为空,则transform函数允许我返回可为空的内容
configure(Foo::bar, { null })
是否可以重构该方法以防止当属性为非空属性时,变换函数无法返回可为空的结果?
答案 0 :(得分:4)
答案 1 :(得分:1)
问题实际上更普遍:
configure(Foo::bar, { Object() })
也可以。因为KProperty1
在其第二个类型参数中是covariant,所以KProperty1<R, String>
(例如)也是KProperty1<R, String?>
,KProperty1<R, CharSequence>
等。这也适用于函数类型(source: S) -> P
。因此,无论您传递什么(单参数)transform
,编译器都会始终找到P
,以使类型适合:属性和函数的返回类型的最小上限。
我可以想到的一个相当丑陋的解决方法是创建一个非协变量包装器类型:
class NonCov<A>(val value: A)
fun <P> configure(property: NonCov<KProperty1<R, P>>, transform: NonCov<(source: S) -> P)>) {
... // use property.value and transform.value
}
然后
class A(val x: String)
fun <P> configure(property: NonCov<kotlin.reflect.KProperty1<A, P>>, transform: NonCov<(source: A) -> P>) {}
fun main(args: Array<String>) {
configure(NonCov(A::x), NonCov { "" }) // compiles
configure(NonCov(A::x), NonCov { null }) // doesn't compile
}