I have the code below
class Sample {
var variable1: SomeClass? = null
var variable2: SomeClass? = null
var variable3: SomeClass? = null
fun checkVariable() {
when {
variable1 != null -> variable1!!.doSomething()
variable2 != null -> variable2!!.doSomething()
variable3 != null -> variable3!!.doSomething()
}
}
}
I'm hoping I can make variableX
after the ->
non-nullable, so I don't need to !!
.
I can avoid !!
with
variable1 !== null -> variable1?.doSomething()
But is there away to do this more elegantly that I can have a non-nullable variable to access the doSomething()
?
CodePudding user response:
The error is not because of the when
. You just cannot smart cast class-level var
s.
In this case, since all your variables are of the same type and you are doing the same thing on all of them, your code can be simplified to:
(variable1 ?: variable2 ?: variable3)?.doSomething()
In other words, you are finding the first non-null out of the three variables, and calling doSomething
on it.
If your variables are not of the same type, and you are doing different things to each of them, you can do:
variable1?.also {
it.doSomething()
} ?: variable2?.also {
it.doSomethingElse()
} ?: variable3?.also {
it.doAnotherThing()
}
CodePudding user response:
Not sure if it's more elegant but you could maybe write this instead:
fun getStrLength() = (variable1 ?: variable2 ?: variable3)?.doSomething()
Another way to remove the !!
is to first store them in local variables like
fun getStrLengths() {
val variable1 = variable1
val variable2 = variable2
val variable3 = variable3
when {
variable1 != null -> variable1.doSomething()
variable2 != null -> variable2.doSomething()
variable3 != null -> variable3.doSomething()
}
}
CodePudding user response:
Lazy initialisation
You could make the properties non-nullable with lateinit var
.
This would prevent the need for any null checks.
You can check to see if the properties are present with isInitialized
instead of a non-null check.
class Sample {
lateinit var variable1: SomeClass
lateinit var variable2: SomeClass
lateinit var variable3: SomeClass
fun checkVariable() {
when {
// so long as a value is initialised, there is no need for null checks
::variable1.isInitialized -> variable1.printName()
::variable2.isInitialized -> variable2.printName()
::variable3.isInitialized -> variable3.printName()
}
}
}
class SomeClass(val name: String) {
fun printName() {
println(name)
}
}
Unsetting values
This can be useful to avoid null checks, but it would prevent 'unsetting' previously set variables with null
.
val sample = Sample()
sample.variable1 = SomeClass("foo")
sample.variable1 = null // ERROR: Null can not be a value of a non-null type SomeClass
Whether unsetting values is required or not depends on your use-case.
Example
fun main() {
val sample = Sample()
println("first check:")
sample.checkVariable()
println("---")
sample.variable3 = SomeClass("Jamie")
println("second check:")
sample.checkVariable()
println("---")
sample.variable2 = SomeClass("Maddie")
println("third check:")
sample.checkVariable()
println("---")
sample.variable1 = SomeClass("Lisa")
println("fourth check:")
sample.checkVariable()
println("---")
}
We can see that as each variable is set, other variables are not called, as they are listed lower in the when
statement.
first check:
---
second check:
Jamie
---
third check:
Maddie
---
fourth check:
Lisa
---