Exercise: Generic Response
You needed to model a response from a server that can be represented as a success or a failure, both of which contain data of a generic type. This is how you modeled it:
sealed class Response<R, E>
class Success<R, E>(val value: R) : Response<R, E>()
class Failure<R, E>(val error: E) : Response<R, E>()
However, you found that this implementation is problematic. To create a Success
object, you need to provide two generic types, but you only need one. To create a Failure
object, you need to provide two generic types, but you only need one. Your task is to fix this problem.
val rs1 = Success(1) // Compilation error
val rs2 = Success("ABC") // Compilation error
val re1 = Failure(Error()) // Compilation error
val re2 = Failure("Error") // Compilation error
You need to define Success
and Failure
in a way that each can be created with only one generic type argument. You want to be able to use Success
and Failure
without specifying generic types, so just use Success(1)
or Failure("Error")
.
You also want to allow Success<Int>
to be upcast to Success<Number>
or to Success<Any>
, and Failure<Error>
to be upcast to Failure<Throwable>
or to Failure<Any>
. You want to be able to use Success<Int>
as Response<Int, Throwable>
.
val rs1 = Success(1)
val rs2 = Success("ABC")
val re1 = Failure(Error())
val re2 = Failure("Error")
val rs3: Success<Number> = rs1
val rs4: Success<Any> = rs1
val re3: Failure<Throwable> = re1
val re4: Failure<Any> = re1
val r1: Response<Int, Throwable> = rs1
val r2: Response<Int, Throwable> = re1
This problem can either be solved in the below playground or you can clone kotlin-exercises project and solve it locally. In the project, you can find code template for this exercise in advanced/generics/Response.kt. You can find there starting code and example usage.
Once you are done with the exercise, you can check your solution here.
sealed class Response<R, E>
class Success<R, E>(val value: R) : Response<R, E>()
class Failure<R, E>(val error: E) : Response<R, E>()
fun usage() {
val rs1 = Success(1)
val rs2 = Success("ABC")
val re1 = Failure(Error())
val re2 = Failure("Error")
val rs3: Success<Number> = rs1
val rs4: Success<Any> = rs1
val re3: Failure<Throwable> = re1
val re4: Failure<Any> = re1
val r1: Response<Int, Throwable> = rs1
val r2: Response<Int, Throwable> = re1
}
Marcin Moskala is a highly experienced developer and Kotlin instructor as the founder of Kt. Academy, an official JetBrains partner specializing in Kotlin training, Google Developers Expert, known for his significant contributions to the Kotlin community. Moskala is the author of several widely recognized books, including "Effective Kotlin," "Kotlin Coroutines," "Functional Kotlin," "Advanced Kotlin," "Kotlin Essentials," and "Android Development with Kotlin."
Beyond his literary achievements, Moskala is the author of the largest Medium publication dedicated to Kotlin. As a respected speaker, he has been invited to share his insights at numerous programming conferences, including events such as Droidcon and the prestigious Kotlin Conf, the premier conference dedicated to the Kotlin programming language.