繁体   English   中英

我如何在 Kotlin 的密封类中编写 Nested Generics

[英]How do I write Nested Generics in Kotlin's Sealed Classes

我正在尝试提供一个数据 model,它允许我执行以下操作:

  • 定义一种Task类型并更改其Status
  • Status可以是进行InProgressCompleted
  • 在已完成Status的情况下,我希望能够添加特定于已完成Task的数据。

最初,我想出了这个数据 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()
}

这里有Task.ATask.B ,其中:

  • 一个完成的Task.A只接受NoResult
  • 一个完成的Task.B只接受TaskBResult

但是,当我运行它时:

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"
            )
        )
    )
}

我收到以下用于设置Task.B初始状态的编译错误:

status = TaskStatus.InProgress
    Type mismatch.
    Required: TaskStatus<TaskResult.TaskBResult>
    Found: TaskStatus.InProgress

有谁知道如何更改数据 model 以便我可以运行此(或非常相似的) main function?

这可以通过非常小的更改工作:只需将TaskStatus协变泛型 class 并将InProgress TaskStatus<Nothing> 当您有不代表 state 的“特殊情况”对象时,这是您可以使用的典型策略。此更改后,您的代码应该编译:

    sealed class Task<R : TaskResult> {

        abstract val status: TaskStatus<R>

        data class A(
            val data: String,
            override val status: TaskStatus<TaskResult.NoResult>,
        ) : Task<TaskResult.NoResult>()

        data class B(
            val data: String,
            override val status: TaskStatus<TaskResult.TaskBResult>,
        ) : Task<TaskResult.TaskBResult>()
    }

    sealed class TaskStatus<out R : TaskResult> {
        object InProgress : TaskStatus<Nothing>()
        data class Completed<R : TaskResult>(val result: R) : TaskStatus<R>()
    }

    sealed class TaskResult {
        object NoResult : TaskResult()
        data class TaskBResult(val resultData: String) : TaskResult()
    }
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"
            )
        )
    )
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM