I'm trying to come up with a data model that allows me to do the following:
- Define a type of
Taskand change itsStatus - This
Statuscan be eitherInProgressorCompleted - In the case of a completed
Status, I want to be able to add data, that is specific to theTaskthat was completed.
Initially, I came up with this data model:
sealed class Task<R : TaskResult> {
abstract val status: TaskStatus<R>
data class A(
val data: String,
override val status: TaskStatus<NoResult>,
) : Task<NoResult>()
data class B(
val data: String,
override val status: TaskStatus<TaskBResult>,
) : Task<TaskBResult>()
}
sealed class TaskStatus<R : TaskResult> {
object InProgress : TaskStatus<NoResult>()
data class Completed<R : TaskResult>(val result: R) : TaskStatus<R>()
}
sealed class TaskResult {
object NoResult : TaskResult()
data class TaskBResult(val resultData: String) : TaskResult()
}
Here you have Task.A and Task.B, where:
- A completed
Task.Aonly acceptsNoResult - A completed
Task.Bonly acceptsTaskBResult
However, when I run this:
fun main() {
val taskA = Task.A(
data = "data",
status = TaskStatus.InProgress
).copy(
status = TaskStatus.Completed(
result = NoResult
)
)
val taskB = Task.B(
data = "data",
status = TaskStatus.InProgress
).copy(
status = TaskStatus.Completed(
result = TaskBResult(
resultData = "resultData"
)
)
)
}
I get the following compile error for setting the initial status of Task.B:
status = TaskStatus.InProgress
Type mismatch.
Required: TaskStatus<TaskResult.TaskBResult>
Found: TaskStatus.InProgress
Does anyone know how to change the data model so I'm allowed to run this (or a very similar) main function?
This could work with a very little change: just make
TaskStatusa covariant generic class and makeInProgressaTaskStatus<Nothing>. This is a typical strategy you can use when you have "special case" objects that represent no state. After this change, your code should compile: