Reputation: 14409
I have the following sealed classes
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()
}
And I am trying to do the following.
//obs is of type Observable<Detail.Result.DownloadWallpaper>
obs.map{ it.copy(hd = true) }
But I cant, for two reasons since DownloadWallpaper
isn't a data class. There's not .copy()
method. How can I tell Kotlin that all classes in this seal class are in fact data classes
?
Secondly, DownloadWallpaper
it self doesn't have an 'hd' field. I could cast this using when How can fix this elegantly?
This solution is quite ugly:
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)
}
Upvotes: 30
Views: 21579
Reputation: 7926
By adding a few abstract methods to your sealed class I was able to access copy methods without explicit type check. See for yourself:
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)
}
Upvotes: 51