let in kotlin help me avoid some if(null?) doSomething.
But I have a problem.
A is the field of the object, And B is the field of Object A. they can be nullbale.
They in code like this.
class Obj {
var a : A?
}
class A {
var b : B?
}
I knew I can do it by double let:
A?.let {
it.B.let {
// a must nonnull
}
}
A?.B?.let {
// how to use A ,without null check again?
}
There are extension functions out there to achieve what you're looking for, you can find them in this thread https://discuss.kotlinlang.org/t/kotlin-null-check-for-multiple-nullable-vars/1946
But honestly, you're probably better of just using a basic if check here, if the variable is mutable you can assign it to a val
first.
val _a = a
val _b = b
if (_a != null && _b != null) {
}
Edit: If you still really want to use let though, for this case you could create a pair and use takeIf
(a to b)
.takeIf { (a, b) ->
a != null && b != null
}
?.let { (a, b) ->
}
However the compiler won't smartcast the values as non-null, so you will still have to perform a non-null (!!) assertion on them.
By default Kotlin avoids null
values and for Null Safety
it provides:
1) Safe Call Operator( ?. )
2) Not-Null Assertion( !! )
3) Elvis Opeartor( ?: )
4) Safe Call with let ( ?.let{...} )
Safe Call Operator( ?. ):Checks if the property is not null before performing any operations.
Not-Null Assertion( !! ) : Explicitly tells the compiler that the property is not null and if it’s null, please throw a null pointer exception (NPE)
Elvis Opeartor( ?: ): It's like ternary operator in java. If property is not null then left expression is returned otherwise right.
Safe Call with let ( ?.let{...} ): It will execute the let block only if property is not null
An example(With Not Null Value inside property):
fun main() {
val name: String? = "Sumit"
println("Safe Call operator: ${name?.length}")
name?.let {
println("Safe Call wih let operator: ${name.length}")
}
val length = name?.length ?: 0
println("Elvis operator : $length")
println("Not Null Assertion Operator : ${name!!.length}")
}
Output (With Not Null Value inside property)
Safe Call operator: 5
Safe Call wih let operator: 5
Elvis operator : 5
Not Null Assertion Operator : 5
Output (With Null Value inside property)(val name: String? = null)
Safe Call operator: null
Elvis operator : 0
Exception in thread "main" kotlin.KotlinNullPointerException
at HelloKt.main(Hello.kt:14)
at HelloKt.main(Hello.kt)
Here, safe call with let is not executed!! And Not-Null assertion operator throws null pointer exception.
Your problem can use not-null assertion operator:
A?.B?.let {
// If A and B are not null then only this block will be executed.
A.someMethod()
B.someMethod()
}
You could implement it like a Swift guard with an elvis operator ?:
fun doSomething() {
val a = A ?: return
val b = B ?: return
doSomethingWith(a, b)
}
Here a
and b
are non-nullable references to the data you hold in In this case you'd just return from your function.