仅当所有参数都不为空时,Kotlin调用函数

xin*_*aiz 11 kotlin kotlin-null-safety

如果所有(或某些)参数都为null,kotlin中是否有一种方法可以阻止函数调用?例如具有功能:

fun test(a: Int, b: Int) { /* function body here */ }
Run Code Online (Sandbox Code Playgroud)

我希望在参数出现时防止空检查null.例如,对于参数:

val a: Int? = null
val b: Int? = null 
Run Code Online (Sandbox Code Playgroud)

我想替换:

a?.let { b?.let { test(a, b) } }
Run Code Online (Sandbox Code Playgroud)

有:

test(a, b)
Run Code Online (Sandbox Code Playgroud)

我想函数定义语法看起来像这样:

fun test(@PreventNullCall a: Int, @PreventNullCall b: Int)
Run Code Online (Sandbox Code Playgroud)

这相当于:

fun test(a: Int?, b: Int?) {
    if(a == null) {
        return
    }

    if(b == null) {
        return
    }

    // function body here
}
Run Code Online (Sandbox Code Playgroud)

类似的东西(或类似的东西)是否可以减少调用者(可能是函数作者)的冗余代码?

zsm*_*b13 6

如果您不希望调用者必须自己进行这些检查,您可以在中间函数中执行空检查,然后在它们通过时调用真正的实现:

fun test(a: Int?, b: Int?) {
    a ?: return
    b ?: return
    realTest(a, b)
}

private fun realTest(a: Int, b: Int) {
    // use params
}
Run Code Online (Sandbox Code Playgroud)

编辑:这是@Alexey Romanov 在下面提出的函数的实现:

inline fun <T1, T2, R> ifAllNonNull(p1: T1?, p2: T2?, function: (T1, T2) -> R): R? {
    p1 ?: return null
    p2 ?: return null
    return function(p1, p2)
}

fun test(a: Int, b: Int) {
    println("$a, $b")
}

val a: Int? = 10
val b: Int? = 5
ifAllNonNull(a, b, ::test)
Run Code Online (Sandbox Code Playgroud)

当然ifAllNonNull,如果您有其他需要其功能的函数,则需要为 2、3 等参数实现该函数。

  • 允许这样做不符合 Kotlin 的 null-safety 方法。您可以将这种方法概括为不需要每个`test` 额外的函数,并得到例如`ifAllNonNull(a, b, ::test)`。 (2认同)

Epi*_*rce 5

您可以为其定义自己的内联函数。

inline fun <R, A> ifNotNull(a: A?, block: (A) -> R): R? =
    if (a != null) {
        block(a)
    } else null

inline fun <R, A, B> ifNotNull(a: A?, b: B?, block: (A, B) -> R): R? =
    if (a != null && b != null) {
        block(a, b)
    } else null

inline fun <R, A, B, C> ifNotNull(a: A?, b: B?, c: C?, block: (A, B, C) -> R): R? =
    if (a != null && b != null && c != null) {
        block(a, b, c)
    } else null

inline fun <R, A, B, C, D> ifNotNull(a: A?, b: B?, c: C?, d: D?, block: (A, B, C, D) -> R): R? =
    if (a != null && b != null && c != null && d != null) {
        block(a, b, c, d)
    } else null
Run Code Online (Sandbox Code Playgroud)

然后你可以这样称呼它

ifNotNull(a, b, c, d) { a, b, c, d ->
    ...
}
Run Code Online (Sandbox Code Playgroud)


leo*_*mer 0

如果您尝试将 null 分配给这两个变量中的任何一个,Int您会发现这不起作用。请参阅注释中的编译错误。

fun test(a: Int, b: Int) { /* function body here */ }

fun main(){
    test(null, 0) //Null can not be value of non-null type Int
    val b : Int? = null
    test(0, b) // Type mismatch. Required: Int - Found: Int?
}
Run Code Online (Sandbox Code Playgroud)

该示例表明,在纯 Kotlin 世界中,test(a: Int, b: Int)不能使用参数进行调用null,甚至不能Int?使用参数进行调用。如果您将 Java 混合在一起,我怀疑是否存在无需null检查的安全解决方案,因为您可以从 Java 端test(Int, Int)使用类型进行调用,这允许 null。IntegerJava“等同于”Int将是@NotNull Integer(这并不是真正的空安全)。