Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
仅当所有参数均不为null时,Kotlin才调用函数_Kotlin_Kotlin Null Safety - Fatal编程技术网

仅当所有参数均不为null时,Kotlin才调用函数

仅当所有参数均不为null时,Kotlin才调用函数,kotlin,kotlin-null-safety,Kotlin,Kotlin Null Safety,如果所有(或部分)参数都为空,kotlin中是否有防止函数调用的方法?例如,具有以下功能: fun test(a: Int, b: Int) { /* function body here */ } 我希望在参数为null的情况下防止空检查。例如,对于参数: val a: Int? = null val b: Int? = null 我想替换: a?.let { b?.let { test(a, b) } } 与: 我认为函数定义语法可以如下所示: fun test(@PreventNu

如果所有(或部分)参数都为空,kotlin中是否有防止函数调用的方法?例如,具有以下功能:

fun test(a: Int, b: Int) { /* function body here */ }
我希望在参数为
null
的情况下防止空检查。例如,对于参数:

val a: Int? = null
val b: Int? = null 
我想替换:

a?.let { b?.let { test(a, b) } }
与:

我认为函数定义语法可以如下所示:

fun test(@PreventNullCall a: Int, @PreventNullCall b: Int)
这相当于:

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

    if(b == null) {
        return
    }

    // function body here
}

这样(或类似)的方法是否可以减少调用者(可能还有函数编写者)的冗余代码?

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

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?
}

该示例显示,在纯Kotlin world中,
测试(a:Int,b:Int)
不能使用
null
甚至
Int?
参数调用。如果你把Java放在混合中,我怀疑没有
null
检查的安全解决方案,因为你可以从Java端调用
test(Int,Int)
类型
Integer
,它允许null。
Int
的Java“等价物”将是
@NotNull Integer
(这不是真正的空安全)。

如果您不希望调用方自己进行这些检查,您可以在中间函数中执行空检查,然后在通过时调用实际实现:

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

private fun realTest(a: Int, b: Int) {
    // use params
}

编辑:下面是@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)
inline fun ifAllNonNull(p1:T1?,p2:T2?,函数:(T1,T2)->R:R?{
p1?:返回空值
p2?:返回空值
返回功能(p1、p2)
}
趣味测试(a:Int,b:Int){
println($a,$b)
}
瓦拉:国际?=10
val b:Int?=5.
ifAllNonNull(a,b,::测试)

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

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

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

不!是你问题的答案(据我所知)

你最好的选择(假设函数没有公开)是你所说的

a?.let { b?.let { test(a, b) } }
如果函数是公开的,并且可能在没有这些检查的情况下被调用,那么您需要将这些检查放在函数中

fun test(a: Int?, b: Int?) {
    if (listOf(a, b).filterNotNull().size < 2) return

    println("Function was called")
}
fun测试(a:Int?,b:Int?){
if(listOf(a,b).filterNotNull().size<2)返回
println(“调用了函数”)
}
Let表示元组(成对和三元组) 我认为OP的精神是语法,所以我的答案集中在为元组类型提供“let”:

示例用法: 扩展功能:
//为成对和三重定义let
有趣的一对。让(f:(P1,P2)->R:R?{
返回f(第一个?:返回null,第二个?:返回null)
}
有趣的三重。让(f:(P1,P2,P3)->R):R?{
返回f(第一个:返回null,第二个:返回null,第三个:返回null)
}
//三元组的可爱“to”语法
中缀有趣的配对。到(第三:P3?):三重{
返回三元组(第一、第二、第三)
}

您可以用另一个单词替换“to”(参见三元组扩展作为指南),也可以扩展到更大的元组(但Kotlin只提供2个开箱即用的元组&遗憾的是,我不认为它是通用的)。

尝试创建一个在循环内接受并检查null的函数。在纯Kotlin world
测试中(a:Int,b:Int)
不能使用
null
甚至
Int?
参数调用。如果你把Java放在混合中,我怀疑没有空检查的安全解决方案。与
Int
相当的Java“等价物”应该是
@NotNull Integer
(这并不是真正的空安全)。这似乎是最好的纯kotlin解决方案,但我不希望有表明参数是可选的函数签名。我想让调用者明白这一点。不幸的是,调用者没有办法相信参数是不可为null的,而是能够安全地将可为null的参数传递给函数。您必须在调用站点或函数内部执行空检查。允许这样做不符合Kotlin的空安全方法。你可以将这种方法推广到每个
测试都不需要一个额外的函数,并得到例如
ifAllNonNull(a,b,::test)
。实际上,我今天早些时候为一个类似的问题编写了这个函数,我已经编辑了我的答案及其实现:)我是按照
ifAllNull
的思路思考的,但我不喜欢它是特定于家庭的。我没有找到避免它的方法。我喜欢巧妙地使用
listOf()
来改变参数的数量
a?.let { b?.let { test(a, b) } }
fun test(a: Int?, b: Int?) {
    if (listOf(a, b).filterNotNull().size < 2) return

    println("Function was called")
}
fun main() {
    val p1: Int? = 10 // or null
    val p2: Int? = 20 // or null
    val p3: Int? = 30 // or null

    val example1 = (p1 to p2).let(::testDouble)
    val example2 = (p1 to p2).let { a, b -> a * b }

    val example3 = (p1 to p2 to p3).let(::testTriple)
    val example4 = (p1 to p2 to p3).let { a, b, c -> a * b * c }
}

fun testDouble(a: Int, b: Int): Int {
    return a + b
}

fun testTriple(a: Int, b: Int, c: Int): Int {
    return a + b + c
}
// Define let for Pair & Triple
fun <P1, P2, R> Pair<P1?, P2?>.let(f: (P1, P2) -> R): R? {
    return f(first ?: return null, second ?: return null)
}

fun <P1, P2, P3, R> Triple<P1?, P2?, P3?>.let(f: (P1, P2, P3) -> R): R? {
    return f(first ?: return null, second ?: return null, third ?: return null)
}

// Cute "to" syntax for Triple
infix fun <P1, P2, P3> Pair<P1?, P2?>.to(third: P3?): Triple<P1?, P2?, P3?> {
    return Triple(first, second, third)
}