Kotlin 如何覆盖密封类字段?

Kotlin 如何覆盖密封类字段?,kotlin,sealed-class,Kotlin,Sealed Class,我在我的服务中创建了一个自定义结果字段(而不是Kotlin的结果),以便在成功和失败的情况下都可以返回消息字段: sealed class Result<T> { data class Success<T>(val value: T, val message: String) : Result<T>() data class Failure<T>(val throwable: Throwable? = null, val mess

我在我的服务中创建了一个自定义结果字段(而不是Kotlin的结果),以便在成功和失败的情况下都可以返回消息字段:

sealed class Result<T> {
    data class Success<T>(val value: T, val message: String) : Result<T>()

    data class Failure<T>(val throwable: Throwable? = null, val message: String) : Result<T>() {
        val isExceptional = throwable != null
        val error: Throwable
            get() = throwable ?: error("Error is undefined in [$this]")
    }
}
只是,kotlin编译器不识别“消息”,因为它不是直接的结果属性,而是成功和失败的属性

我试图重写消息字段并在结果类中定义它。但是我犯了一个错误

Error:(10, 38) Kotlin: 'message' in 'Result' is final and cannot be overridden

那么,如何访问Result.message而不将Result实例强制转换为其派生的实现类(成功或失败)?

1-您可以将它们标记为打开

open val message: String = ""
2-您可以将其定义为抽象的

abstract val message: String

1-您可以将其标记为打开

open val message: String = ""
2-您可以将其定义为抽象的

abstract val message: String

我发现一个干净的解决方案如下


而Kotlin不允许我们重写密封的类成员。它确实允许我们覆盖接口成员

因此,我为消息字段创建了一个简单的接口,并从结果类实现了它:

interface ResultMessage {
    val message: String
}

sealed class Result<T> : ResultMessage

// Now I'm able to override the message field simply, with no error
data class Success<T>(val value: T, override val message: String) : Result<T>()

data class Failure<T>(val throwable: Throwable? = null, override val message: String) : Result<T>() {
    val isExceptional = throwable != null
    val error: Throwable
        get() = throwable ?: error("Error is undefined in [$this]")
}
接口结果消息{
val消息:字符串
}
密封类结果:ResultMessage
//现在我可以简单地覆盖消息字段,没有错误
数据类成功(val值:T,覆盖val消息:字符串):结果()
数据类失败(val-throwable:throwable?=null,重写val消息:字符串):结果(){
val IsException=可丢弃!=null
val错误:可丢弃
get()=throwable?:错误(“错误在[$this]中未定义”)
}

我找到的一个干净的解决方案如下


而Kotlin不允许我们重写密封的类成员。它确实允许我们覆盖接口成员

因此,我为消息字段创建了一个简单的接口,并从结果类实现了它:

interface ResultMessage {
    val message: String
}

sealed class Result<T> : ResultMessage

// Now I'm able to override the message field simply, with no error
data class Success<T>(val value: T, override val message: String) : Result<T>()

data class Failure<T>(val throwable: Throwable? = null, override val message: String) : Result<T>() {
    val isExceptional = throwable != null
    val error: Throwable
        get() = throwable ?: error("Error is undefined in [$this]")
}
接口结果消息{
val消息:字符串
}
密封类结果:ResultMessage
//现在我可以简单地覆盖消息字段,没有错误
数据类成功(val值:T,覆盖val消息:字符串):结果()
数据类失败(val-throwable:throwable?=null,重写val消息:字符串):结果(){
val IsException=可丢弃!=null
val错误:可丢弃
get()=throwable?:错误(“错误在[$this]中未定义”)
}

您可以在
结果
类中声明抽象属性:

sealed class Result<T> {
    abstract val message: String
    data class Success<T>(val value: T, override val message: String) : Result<T>()

    data class Failure<T>(val throwable: Throwable? = null, override val message: String) : Result<T>() {
        val isExceptional = throwable != null
        val error: Throwable
            get() = throwable ?: error("Error is undefined in [$this]")
    }
}
密封类结果{
抽象val消息:字符串
数据类成功(val值:T,覆盖val消息:字符串):结果()
数据类失败(val-throwable:throwable?=null,重写val消息:字符串):结果(){
val IsException=可丢弃!=null
val错误:可丢弃
get()=throwable?:错误(“错误在[$this]中未定义”)
}
}

不过,您的解决方案也是一个选项

您可以在
结果
类中声明一个抽象属性:

sealed class Result<T> {
    abstract val message: String
    data class Success<T>(val value: T, override val message: String) : Result<T>()

    data class Failure<T>(val throwable: Throwable? = null, override val message: String) : Result<T>() {
        val isExceptional = throwable != null
        val error: Throwable
            get() = throwable ?: error("Error is undefined in [$this]")
    }
}
密封类结果{
抽象val消息:字符串
数据类成功(val值:T,覆盖val消息:字符串):结果()
数据类失败(val-throwable:throwable?=null,重写val消息:字符串):结果(){
val IsException=可丢弃!=null
val错误:可丢弃
get()=throwable?:错误(“错误在[$this]中未定义”)
}
}

不过,您的解决方案也是一种选择

谢谢,这些都是不错的选择!我找到了另一个干净的解决方案,我将在下面解释。对于open,您需要初始化变量。您还需要在这两种情况下覆盖该值。谢谢,这些都是很好的选项!我找到了另一个干净的解决方案,我将在下面解释。对于open,您需要初始化变量。在这两种情况下,您还需要重写该值。“而Kotlin不允许我们重写密封的类成员。它允许我们重写接口成员。”它允许您重写密封的类成员。您只需将它们标记为
open
abstract
,与任何其他类中的标记相同。您的解决方案与添加
摘要
成员相同,但有额外的步骤。酷。我认为在这里使用
abstract
是最好的方法。“而Kotlin不允许我们重写密封的类成员。它允许我们重写接口成员。”它允许您重写密封的类成员。您只需将它们标记为
open
abstract
,与任何其他类中的标记相同。您的解决方案与添加
摘要
成员相同,但有额外的步骤。酷。我认为使用
abstract
是最好的方法。