This is sorta ugly:
override var x1: Double = 0.0 //x-coordinate for object
get() =
if(hasParent) { //if there is no parent, we can't have an x coord anyway - nowhere to draw this object
if (hasPrev) { //we won't always have a previous event, thus the other branch
prev!!.x2 + parent!!.mEventSpacing
} else {
parent!!.mEventStartX
}
} else {
field
}
Is it possible to replace it with something like the following?
override var x1: Double = 0.0
get() = (prev?.x2 + parent?.mEventSpacing) ?: parent?.mEventStartX ?: field
The logic is obviously not right there, but is there something close to this? Or would it require some serious fandangling to do something that simple?
Assume that hasParent = parent != null
and hasPrev = prev != null
.
Also assume parent
and prev
are defined as val
, not var
in the if
or when
statements because I don't like to add !!
many times.
What you are doing is, using when
expression:
override var x1: Double = 0.0 //x-coordinate for object
get() = when {
parent != null && prev != null -> prev.x2 + parent.mEventSpacing
parent != null && prev == null -> parent.mEventSpacing
parent == null -> field
}
You can use the combination of ?.
operator and let
function (refer to Safe Calls section):
override var x1: Double = 0.0 //x-coordinate for object
get() =
parent?.let { pr -> prev?.let { pv -> pv.x2 + pr.mEventSpacing } ?: pr.mEventSpacing } ?: field
let
function executes the parameter block whose parameter is what called let
, and return the last expression in the parameter block.
For example, 1.let { it + 2 }
is 3
.
x?.let
executes the let
function if x
is not null.
i.e., x?.let { ... }
is the same as if (x != null) x.let { ... } else null)
.
Here,
if parent == null
, then
parent?.let { pr -> prev?.let { pv -> pv.x2 + pr.mEventSpacing } ?: pr.mEventSpacing }
is just null
.
if parent != null
, then
parent?.let { pr -> prev?.let { pv -> pv.x2 + pr.mEventSpacing } ?: pr.mEventSpacing }
is the same as prev?.let { pv -> pv.x2 + parent!!.mEventSpacing } ?: parent!!.mEventSpacing
You can shorten this. if prev == null
, then prev.x2
can be treated as 0
. So
override var x1: Double = 0.0 //x-coordinate for object
get() =
parent?.let { pr -> (prev?.let { pv -> pv.x2 } ?: 0) + pr.mEventSpacing } ?: field
You can further shorten this by using it
in the inner let
function.
override var x1: Double = 0.0 //x-coordinate for object
get() =
parent?.let { pr -> (prev?.let { it.x2 } ?: 0) + pr.mEventSpacing } ?: field
Also, you can use combination of run
and let
. (Google kotlin run
or kotlin run vs let
if you don't know it.)
override var x1: Double = 0.0 //x-coordinate for object
get() =
parent?.run { (prev?.let { it.x2 } ?: 0) + mEventSpacing } ?: field
But I think using when
is the eastest to understand.
Well, if parent
and prev
were defined as var
, using when
expression with !!
can raise a NPE, whereas using ?.let
, ?.run
, and ?:
will never raise a NPE in a multi-core device. To prevent this, you can define local val
s with the current values in the getter function so that you will never need to use the !!
operator.