【问题标题】:How do I override sealed class fields?如何覆盖密封类字段?
【发布时间】:2021-02-28 16:06:10
【问题描述】:

我在我的服务中创建了一个自定义结果字段(而不是 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 而不将结果实例转换为它的派生实现类(成功或失败)?

【问题讨论】:

    标签: kotlin sealed-class


    【解决方案1】:

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

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

    【讨论】:

    • “虽然 Kotlin 不允许我们覆盖密封的类成员。它允许我们覆盖接口成员。”它确实允许您覆盖密封的类成员。您只需将它们标记为openabstract,与任何其他类相同。您的解决方案与添加abstract 成员相同,但需要额外的步骤。
    • 酷。我认为在这里使用abstract 是最好的方法。
    【解决方案2】:

    您可以在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]")
        }
    }
    

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

    【讨论】:

      【解决方案3】:

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

      open val message: String = ""
      

      2- 你可以抽象地定义它们

      abstract val message: String
      

      【讨论】:

      • 谢谢,这些都是不错的选择!我找到了另一个干净的解决方案,我将在下面解释。
      • 为了打开,需要初始化变量。您还需要在这两种情况下覆盖该值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-12
      • 1970-01-01
      • 2013-02-25
      相关资源
      最近更新 更多