如何将Kotlin的`with`表达式用于可空类型

mem*_*izr 11 nullable with-statement kotlin

下面的代码将无法编译,因为该变量myType可以为null.有没有办法with在Kotlin中为可空类型执行块?

    val myType: MyType? = null
    with(myType) {
        aMethodThatBelongsToMyType()
        anotherMemberMethod()            
    }
Run Code Online (Sandbox Code Playgroud)

Ing*_*gel 17

您可以使用后缀将可空类型转换为非可空类型!!:

with(myType!!) {
    aMethodThatBelongsToMyType()
    anotherMemberMethod()            
}
Run Code Online (Sandbox Code Playgroud)

如果该值确实为null,则会抛出一个NullPointerException,因此通常应该避免这种情况.

更好的方法是通过进行空安全调用并使用apply扩展函数代替以下内容来使代码块的执行依赖于非空值with:

myType?.apply {
    aMethodThatBelongsToMyType()
    anotherMemberMethod()            
}
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用if语句检查值是否为非null .编译器会将智能强制转换插入if块中的非可空类型:

if (myType != null) {
    with(myType) {
        aMethodThatBelongsToMyType()
        anotherMemberMethod()            
    }
}
Run Code Online (Sandbox Code Playgroud)


Jac*_*man 5

您可以定义自己的with函数来接受可空值,然后根据对象是否为空来确定是否实际运行。

像这样:

fun <T, R> with(receiver: T?, block: T.() -> R): R? {
    return if(receiver == null) null else receiver.block()
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以按照示例中您想要的方式调用代码,没有任何问题,并且null如果您传入的是 ,结果将相等null

或者,如果代码块应该(并且可以)以任何一种方式运行,即使是myTypenull那么您也可以像这样定义它:

fun <T, R> with(receiver: T?, block: T?.() -> R): R {
    return receiver.block()
}
Run Code Online (Sandbox Code Playgroud)