问题描述
我在我的服务中创建了一个自定义结果字段(而不是 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 而不将结果实例转换为它的派生实现类(成功或失败)?
解决方法
1- 您可以将它们标记为打开
open val message: String = ""
2- 你可以定义它们抽象
abstract val message: String
,
您可以在 Result
类中声明抽象属性:
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]")
}
}
不过,您的解决方案也是一种选择
,我找到的一个干净的解决方案如下。
虽然 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]")
}