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

如何修改密封接口属性?Optics未生成对应属性的解决方案探讨

问题

我尝试修改一个密封接口的属性,发现Optics并未为接口的属性生成对应的操作工具,仅能访问子类的SealedType.typeA.value。请问是否必须手动编写如下Lens来实现属性修改,还是可以通过Prism/Iso等其他我忽略的Optics工具来实现?

测试代码

@Test
fun `Modify field on sealed interface`() {
    val orgA = SealedType.TypeA(0)

    // property [value] is not generated by optics, only `SealedType.typeA.value` exists.
    val newA = SealedType.value.modify(orgA) { it + 1}
    
    expectThat(newA.value).isEqualTo(1)
}

@optics sealed interface SealedType {
    val value: Int
    companion object;

    @optics data class TypeA(
        override val value: Int
    ) : SealedType {
        companion object
    }

    // TypeB ... same as TypeA
    
}

手动编写的Lens示例

companion object {
    val value: Lens<SealedType, Int> inline get() = Lens(
        get = { subject ->
            subject.value
        },
        set = { subject, newValue ->
            when (subject) {
                is TypeA -> subject.copy(value = newValue)
                is TypeB -> subject.copy(value = newValue)
            }
        }
    )
}
解决方案

Optics自动生成工具时,只会针对具体子类的属性生成对应的操作器,不会为密封接口的抽象属性自动生成工具。

是否必须手动编写Lens?

是的,你当前手动实现的Lens是最直接的解决方案。这个Lens<SealedType, Int>需要覆盖所有子类的copy逻辑,而Optics无法自动推断所有子类的实现细节——如果后续新增子类,你还需要手动更新Lens的set分支。

能否用Prism/Iso替代?

  • Prism:Prism用于处理父类型到单个子类型的可选转换,只能针对某一个子类操作,无法同时处理所有子类的value修改,不适用你的场景。
  • Iso:Iso用于双向同构的类型转换,密封接口实例包含的信息远不止value,和Int并非同构关系,因此也不适用。

优化建议

如果后续会新增更多子类,可以在密封接口中定义抽象的copyWithValue方法,让每个子类实现,这样Lens的逻辑可以简化,扩展性更好:

@optics sealed interface SealedType {
    val value: Int
    fun copyWithValue(newValue: Int): SealedType
    companion object;

    @optics data class TypeA(
        override val value: Int
    ) : SealedType {
        companion object
        override fun copyWithValue(newValue: Int) = copy(value = newValue)
    }

    // TypeB同理实现copyWithValue方法
}

// 简化后的Lens实现
companion object {
    val value: Lens<SealedType, Int> inline get() = Lens(
        get = { it.value },
        set = { subject, newValue -> subject.copyWithValue(newValue) }
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 20:50:03