Question: How to check certain combinations of inp...
# getting-started
a
Question: How to check certain combinations of inputs in Kotlin I have a data class as below:
Copy code
data 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.
Copy code
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?
j
If these constraints are generally applicable (not only in
bar
), 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:
Copy code
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:
Copy code
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
1
The above very nice but of course only relevant if these allowed combinations of fields are globally applicable. If these constraints are only true within
bar
, you could use:
Copy code
require(condition) { "failure message" }
Instead of:
Copy code
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 fishy
3
a
Thanks for the suggestions @Joffrey!