You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin 带继承与必填参数的数据结构最佳实践及实现方案

问题原因说明
  • 原代码父类amount字段声明为String类型,和你期望调用时传入的数值类型12不匹配
  • 子类继承父类时没有透传父类要求的必填参数和可选参数,导致实例化子类时无法传入父类定义的参数
  • 密封类本身就不允许直接实例化,天然满足「仅允许实例化子类对象」的要求,不需要额外限制
基础实现方案(无工厂模式,匹配你期望的调用写法)

直接在子类声明时透传父类的所有参数,固定的type参数由子类内部赋值即可:

enum class SupportedTypes {
    ONE, TWO
}

sealed class TransferObject(
    val type: SupportedTypes,
    val system: String = "sys1",
    val amount: Int,
    val awaitReceipt: Boolean = true
) {
    data class TransferObject_ONE(
        val system: String = "sys1",
        val amount: Int,
        val awaitReceipt: Boolean = true,
        val obligatoryString: String
    ) : TransferObject(SupportedTypes.ONE, system, amount, awaitReceipt)

    data class TransferObject_TWO(
        val system: String = "sys1",
        val amount: Int,
        val awaitReceipt: Boolean = true,
        val obligatoryInt: Int
    ) : TransferObject(SupportedTypes.TWO, system, amount, awaitReceipt)
}

调用方式完全符合你的预期:

val obj1 = TransferObject.TransferObject_ONE(system = "sys3", obligatoryString = "myString", amount = 12)
// 也可以省略有默认值的参数
val obj2 = TransferObject.TransferObject_TWO(amount = 20, obligatoryInt = 5)

该方案的优势:

  • 编译期强制校验所有必填参数,缺参会直接编译报错,不需要运行时判断
  • 没有额外封装成本,调用写法完全匹配需求
  • 天然限制仅能实例化子类,父类无法直接创建对象
工厂模式适用场景与实现

如果你的场景有以下需求,可以选择叠加工厂模式:

  • 实例化前需要统一做参数校验(比如amount必须大于0、system不能为空)
  • 需要隐藏子类实现,不对外暴露子类类名
  • 实例化时需要统一注入日志、埋点等横切逻辑

工厂模式实现示例:

enum class SupportedTypes {
    ONE, TWO
}

sealed class TransferObject(
    val type: SupportedTypes,
    val system: String = "sys1",
    val amount: Int,
    val awaitReceipt: Boolean = true
) {
    // 子类构造器私有化,仅允许通过工厂方法实例化
    data class TransferObject_ONE private constructor(
        val system: String = "sys1",
        val amount: Int,
        val awaitReceipt: Boolean = true,
        val obligatoryString: String
    ) : TransferObject(SupportedTypes.ONE, system, amount, awaitReceipt)

    data class TransferObject_TWO private constructor(
        val system: String = "sys1",
        val amount: Int,
        val awaitReceipt: Boolean = true,
        val obligatoryInt: Int
    ) : TransferObject(SupportedTypes.TWO, system, amount, awaitReceipt)

    companion object {
        fun createOne(
            system: String = "sys1",
            amount: Int,
            awaitReceipt: Boolean = true,
            obligatoryString: String
        ): TransferObject {
            require(amount > 0) { "amount必须大于0" }
            require(system.isNotBlank()) { "system不能为空" }
            return TransferObject_ONE(system, amount, awaitReceipt, obligatoryString)
        }

        fun createTwo(
            system: String = "sys1",
            amount: Int,
            awaitReceipt: Boolean = true,
            obligatoryInt: Int
        ): TransferObject {
            require(amount > 0) { "amount必须大于0" }
            return TransferObject_TWO(system, amount, awaitReceipt, obligatoryInt)
        }
    }
}
// 调用示例
val obj = TransferObject.createOne(system = "sys3", amount = 12, obligatoryString = "myString")

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 04:00:01