首页 > 解决方案 > 如何覆盖密封类字段?

问题描述

我在我的服务中创建了一个自定义结果字段(而不是 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]")
    }
}

然后在另一个类中,我调用了一个产生此结果的方法并希望记录 Result.message

logger.info { "Finished with message [${result.message}]." }

只是,kotlin 编译器无法识别“消息”,因为它不是 Result 的直接属性,而是 Success 和 Failure 的属性。

我试图覆盖消息字段并在 Result 类中定义它。但我得到一个错误。

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

那么,如何在不将结果实例强制转换为它的派生实现类(成功或失败)的情况下访问 Result.message 呢?

标签: kotlinsealed-class

解决方案


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

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

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

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

推荐阅读