Amol
09/23/2021, 10:23 AMdata class foo(
val a: T?,
val b: U?,
val c: V?,
val d: X?
)
This is sent as an arg to a function
bar(val foo: Foo)
Now in this function bar
, I want to allow only certain combinations of foo's members
e.g.
if(a!=null){
// If a is input, nothing else is allowed
if(b!=null || c!=null || d!= null) throw Exception()
}
if(b!=null){
// If b is input, nothing else is allowed
if(a!=null || c!=null || d!= null) throw Exception()
}
if(c!=null){
// If c is input, d is allowed, a and b not allowed
if(a!=null || b!=null ) throw Exception()
}
Obviously, more the args, the worse it gets. What is a cleaner way of doing this?Joffrey
09/23/2021, 10:25 AMbar
), the best way would be IMO to redesign the Foo
class so only "correct" instances can be created in the first place. Maybe you want a sealed class
instead to express the different valid combinations of parameters:
sealed class Foo {
data class OnlyA(val a: T): Foo()
data class OnlyB(val b: U): Foo()
data class CAndMaybeD(val c: V, val d: X?): Foo()
}
Then you just have to check which case you are in using a much simpler when
statement:
fun bar(foo: Foo) {
when(foo) {
is Foo.OnlyA -> // do something with foo.a
is Foo.OnlyB -> // do something with foo.b
is Foo.CAndMaybeD -> // do something with foo.c and foo.d (d can be null)
}
}
Smart cast will automatically make the correct properties available on foo
Joffrey
09/23/2021, 10:32 AMbar
, you could use:
require(condition) { "failure message" }
Instead of:
if (condition) {
throw IllegalArgumentException("failure message")
}
However, if you're in this case, I'd really like to know your real-life use case, because checking a lot of properties this way seems fishyAmol
09/23/2021, 11:22 AM