Richard
03/05/2025, 7:27 AMenum class ToggleValue {
YES,
NO,
UNKNOWN
}
val ToggleValue.asBoolean: Boolean? // this one
get() = when (this) {
ToggleValue.YES -> true
ToggleValue.NO -> false
ToggleValue.UNKNOWN -> null
}
val Boolean?.asToggleValue: ToggleValue
get() = when (this) {
true -> ToggleValue.YES
false -> ToggleValue.NO
null -> ToggleValue.UNKNOWN
}
Joffrey
03/05/2025, 8:31 AMKlitos Kyriacou
03/05/2025, 11:52 AMasXxx()
functions, so wouldn't it be more consistent to make it asBoolean()
? Maybe there is already some precedence that makes properties idiomatic but I'm not aware of such.Joffrey
03/05/2025, 11:58 AMasXxx()
function is the general convention. But in general with enums that represent some values, I like to keep the mapping in one place and not repeat it. Something like this:
enum class ToggleValue(val boolValue: Boolean?) {
YES(boolValue = true),
NO(boolValue = false),
UNKNOWN(boolValue = null);
companion object {
fun of(value: Boolean?) = entries.first { it.boolValue == value }
}
}
fun Boolean?.asToggleValue(): ToggleValue = ToggleValue.of(this)
The companion of()
could also be inlined, and we could just keep the extension:
enum class ToggleValue(val boolValue: Boolean?) {
YES(boolValue = true),
NO(boolValue = false),
UNKNOWN(boolValue = null),
}
fun Boolean?.asToggleValue(): ToggleValue = ToggleValue.entries.first { it.boolValue == this }
Richard
03/05/2025, 11:59 AMEdgar Avuzi
03/05/2025, 3:41 PMEdgar Avuzi
03/05/2025, 3:46 PMdependencies {
implementation("org.apache.commons:commons-collections4:4.4") // Check latest version
}
And then
import org.apache.commons.collections4.bidimap.DualHashBidiMap
val toggleToBooleanMap =
DualHashBidiMap<ToggleValue, Boolean?>().apply {
put(ToggleValue.YES, true)
put(<http://ToggleValue.NO|ToggleValue.NO>, false)
put(ToggleValue.UNKNOWN, null)
}
// Reverse lookup
val booleanToToggleMap = toggleToBooleanMap.inverseBidiMap()
// Usage
val booleanValue = toggleToBooleanMap[ToggleValue.YES] // true
val toggleValue = booleanToToggleMap[false] // <http://ToggleValue.NO|ToggleValue.NO>
Joffrey
03/05/2025, 3:47 PMAdam S
03/05/2025, 4:17 PMDavid Breneisen
03/07/2025, 1:35 PMKlitos Kyriacou
03/07/2025, 2:17 PMBoolean?
but mean different things.David Breneisen
03/07/2025, 2:19 PMKlitos Kyriacou
03/07/2025, 2:26 PMenum class ToggleValue { as above }
enum class LedStatus { ON, OFF, UNKNOWN }
fun foo(switchPosition: ToggleValue, lightOn: LedStatus)
fun foo(YES, ON) // ok
fun foo(ON, YES) // compile error
fun foo(true, false) // prone to runtime logic errors if named parameters are not used
Basically the same type safety concepts that value classes are used for.Edgar Avuzi
03/07/2025, 2:31 PMJoffrey
03/07/2025, 2:32 PMDavid Breneisen
03/07/2025, 2:33 PMDavid Breneisen
03/07/2025, 2:35 PMKlitos Kyriacou
03/07/2025, 5:14 PMeverything that would be a boolean parameterYou'd be surprised how few these are. Yes, your application may have hundreds of boolean variables and dozens of functions that take boolean parameters, but these will represent only a small set of distinct entity types.