如何在swift中轻松复制不可变结构,仅改变某些字段[如kotlin数据类复制方法]?

Ori*_*rds 3 swift swift-structs

我有一个像这样的swift结构:

struct LogicalState {
  let a: String?
  let b: Bool
  let c: Int
}
Run Code Online (Sandbox Code Playgroud)

以及这种状态的可变实例.注意状态中的属性都是let,所以struct本身是不可变的.

var _state: LogicalState
Run Code Online (Sandbox Code Playgroud)

我想要做的是强制执行一种模式,允许更新状态,但所有更新必须是原子的 - 我不想简单地使a,b和c变为可变,因为这将允许a和b独立更改.我需要控制更新并应用验证(例如,要强制执行,如果更改a,您还必须同时更改b)

我可以通过简单地覆盖整个结构来做到这一点

_state = LogicalState(a: "newA", b: false, c: _state.c)
Run Code Online (Sandbox Code Playgroud)

但是,正如您所看到的,必须为不改变的属性显式引用旧状态(_state.c)是烦人且有问题的,尤其是当您有更多属性时.我的真实世界的例子有10个.

在kotlin中,他们有"数据类",它们公开了一个"复制"方法,它允许你只改变你想要的参数.如果swift支持这样的东西,语法将如下所示

func copy(a: String? = self.a, b:Bool = self.b, c:Int = self.c) ...
Run Code Online (Sandbox Code Playgroud)

问题是,= self.aswift中不存在语法,我不确定我有哪些其他选项?

如何解决这个问题的任何解决方案将非常感激

Mik*_*nov 6

想想,您可以使用复制(...)方法扩展结构,将nil值作为默认值,并将其替换为实例,否则使用非nil.像这样的事情:

extension LogicalState {
    func copy(a: String? = nil, b: Bool? = nil, c: Int? = nil) -> LogicalState {
        return LogicalState(a: a ?? self.a, b: b ?? self.b, c: c ?? self.c)
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,您可以使用它来复制实例,同时改变所需的参数:

let state = LogicalState(a: "A", b: false, c: 10)
let stateCopy1 = state.copy(c: 30)
let stateCopy2 = state.copy(a: "copy 2")
Run Code Online (Sandbox Code Playgroud)