0

I have a situation whereby I am creating a rest client in kotlin as a practical learning exercise and have recently come up against this:

             data class ai constructor(val statusCode: Int,
                                       val a: Long? = null,
                                       val b: Long? = null,
                                       val c: Date? = null,
                                       val d: Long? = null,
                                       val e: String? = null,
                                       val f: String? = null)

The issue is this, if I get a 200 returned i will have the data to populate 'a' through 'f' but if instead i get a 401 or pretty much any other status code i will not have the data to populate 'a' through 'f' and therefore i have opted for the above solution where I only force the status code which i will always get back to not be null and then defaulted every other value to null.

I don't want to go down the route of setting defaults to things like "" or -1 because then there is always the chance that this data will somehow get through if a user does not check the status code.

Really i want to convey that the information is not present, it seems like this would do that but I wondered if there is a better way.

user1383163
  • 577
  • 1
  • 7
  • 24
  • You could always have another class `Something` to hold the `Long, Long, Date, Long, String, String`, and then store a `Something?` here. – Louis Wasserman Jun 20 '18 at 05:07

1 Answers1

2

You could consider using a sealed class for this:

sealed class Result

data class Success constructor(val statusCode: Int = 200,
                               val a: Long,
                               val b: Long,
                               val c: Date,
                               val d: Long,
                               val e: String,
                               val f: String): Result()

data class Failure(val statusCode: Int): Result()

(I don't know if the explicit constructor for your class was intentional, if there are annotations on it, etc.)

This way if you have a successful call, you'll create a Success instance, and if you have a failed call, you can create a Failure instance which doesn't even contain the properties representing the data received (come to think of it, you could move statusCode to the Result class, that's another choice to make).

Here's how you could then handle these results:

fun processResult(result: Result) {
    when (result) {
        is Success -> { /* Use result, which is smart cast to a Success now */ }
        is Failure -> { /* Use result, which is smart cast to a Failure now */ }
    }
}
zsmb13
  • 85,752
  • 11
  • 221
  • 226
  • may i ask what you mean by explicit constructor, is there an implicit form of the above ? – user1383163 Jun 20 '18 at 06:04
  • 1
    Compare the way `Success` and `Failure` have their constructors implemented. One of them has the `constructor` keyword explicitly written down, while the other omits it. You only need the keyword there if you need to annotate the constructor (for example, for dependency injection). – zsmb13 Jun 20 '18 at 06:32