【问题标题】:Sealed data class in KotlinKotlin 中的密封数据类
【发布时间】:2020-04-15 14:19:41
【问题描述】:

我有以下密封类

sealed class DownloadWallpaper : Result() {
    data class Progress(val hd: Boolean = false, ...) : DownloadWallpaper() 
    data class Success(val hd: Boolean = false, ...) : DownloadWallpaper()
    data class Error(val hd: Boolean = false, ...) : DownloadWallpaper()
}

我正在尝试执行以下操作。

//obs is of type Observable<Detail.Result.DownloadWallpaper> 
obs.map{ it.copy(hd = true) }

但我不能,有两个原因,因为DownloadWallpaper 不是数据类。没有.copy() 方法。如何告诉 Kotlin 这个密封类中的所有类实际上都是data classes

其次,DownloadWallpaper 它本身没有“hd”字段。我可以使用 when 如何优雅地解决这个问题? 这个解决方案很丑:

when (it) {
           is Detail.Result.DownloadWallpaper.Success -> it.copy(hd = true)
           is Detail.Result.DownloadWallpaper.Progress -> it.copy(hd = true)
           is Detail.Result.DownloadWallpaper.Error -> it.copy(hd = true)
 }

【问题讨论】:

  • 首先,你不能,copy 是自动生成的:/ data classes 不幸的是在继承方面做得不好
  • 是的,这就是我所害怕的。我想建议的解决方案还不错,但我会把这个问题留在这里,以防有人提出更好的解决方案
  • 如果你把你的解决方案放到DownloadWallpaper的方法中,那么你可以在任何地方重复使用它

标签: kotlin


【解决方案1】:

通过向您的密封类添加一些抽象方法,我能够访问复制方法而无需显式类型检查。自己看:

sealed class DownloadWallpaper {
    abstract val hd: Boolean
    abstract fun copy(hd: Boolean): DownloadWallpaper
}

data class Progress(override val hd: Boolean = false, val a: Any) : DownloadWallpaper() {
    override fun copy(hd: Boolean) = copy(hd = hd, a = a)
}
data class Success(override val hd: Boolean = false, val s: String) : DownloadWallpaper() {
    override fun copy(hd: Boolean) = copy(hd = hd, s = s)
}
data class Error(override val hd: Boolean = false, val c: Int) : DownloadWallpaper() {
    override fun copy(hd: Boolean) = copy(hd = hd, c = c)
}

fun main() {
    val dw: DownloadWallpaper = Progress()
    val newDw = dw.copy(hd = false)
    val newDwSameHd = dw.copy(hd = dw.hd)
}

【讨论】:

  • 这是密封类的一个很棒但被遗忘的功能。由于类型转换的减少,它有助于减少样板代码。它应该是密封类中的默认值,不需要抽象类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-25
  • 1970-01-01
相关资源
最近更新 更多