Kotlin-防止不可为空的泛型函数返回空值

时间:2019-02-18 01:33:10

标签: kotlin

我有以下方法

fun <P> configure(property: KProperty1<R, P>, transform: (source: S) -> P) {
    ...
}

如果我使用Foo::bar调用此函数,其中::bar不可为空,则transform函数允许我返回可为空的内容

configure(Foo::bar, { null })

是否可以重构该方法以防止当属性为非空属性时,变换函数无法返回可为空的结果?

2 个答案:

答案 0 :(得分:4)

代替

fun <P> configure(...)

尝试一下

fun <P : Any> configure(...)

由于doc

  

默认上限(如果未指定)是任何?

答案 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
}