简体   繁体   English

在swift中如何使用只有一个不同字段的结构复制结构

[英]In swift how to copy a struct with one with only one different field

If I have a swift struct 如果我有一个快速的结构

struct Person {
  let firstName: String
  let lastName: String
  let gender: Gender
  let height: Float
  let weight: Float
  let age: Int
}

If have an object a of type Person , from time to time, only one of the field changed, like lastName when the person gets married, age when the person had a birthday etc. but I don't want to create a mutating func for each of the fields, nor do I want to write a lot of boilerplate to construct a new struct passing in all those fields again. 如果有一个对象a类型的Person ,不时地,仅该领域的一个改变,像lastName当人结婚,年龄当人过了一个生日等,但我并不想创建一个mutating func为每个字段,我也不想编写很多样板来构造一个新的结构,再次传递所有这些字段。 Is there a better to to achieve something like 有没有比这更好的事情了

let newPerson = oldPerson.copy(lastName = "Married")

I know this is a really neat feature in scala with case classes, but I have yet to see this feature used in swift. 我知道这是一个非常简洁的scala与case类的功能,但我还没有看到swift中使用的这个功能。 May I know how can I achieve this? 我可以知道如何实现这一目标吗? Do you guys think it should be a baked in feature in swift? 你们认为它应该是swift的特色吗? Maybe we can make a swift evolution proposal? 也许我们可以提出一个快速的进化建议?

I don't know if there is an elegant solution. 我不知道是否有一个优雅的解决方案。 One option would be to define a copy method which takes optional parameters for each property, which default to the current property values: 一种选择是定义一个复制方法,该方法为每个属性采用可选参数,默认为当前属性值:

struct Person {
    let firstName: String
    let lastName: String
    let age: Int

    func copy(firstName: String? = nil, lastName: String? = nil, age: Int? = nil) -> Person {
        return Person(firstName: firstName ?? self.firstName,
                      lastName: lastName ?? self.lastName,
                      age: age ?? self.age)
    }
}


let john = Person(firstName: "John", lastName: "Doe", age: 29)
let jane = john.copy(firstName: "Jane")
print(jane) // Person(firstName: "Jane", lastName: "Doe", age: 29)

A copy function of Person can naturally have default value for its arguments, which would allow calling it with only a subset of the properties of person. Personcopy函数自然可以为其参数设置默认值,这样只允许使用person属性的子集调用它。 The problem is that we may not use self to refer to what values we'd like to use as default. 问题是我们可能不会使用self来指代我们希望默认使用的值。 We can, however, refer to static members of a class (fir convenience, say static members of Person ), which would allow us to create something along the lines 但是,我们可以引用一个类的静态成员(fir方便,比如Person静态成员),这将允许我们创建一些类似的东西

struct Person {
    static var currentObjFirstName: String = ""
    static var currentObjLastName: String? = ""
    // ...
    static var currentObjAge: Int = 0

    let firstName: String
    let lastName: String?
    // ...
    let age: Int

    init(firstName: String, lastName: String?, age: Int) {
        self.firstName = firstName
        self.lastName = lastName
        self.age = age
    }

    func prepareCopy() -> Person {
        Person.currentObjFirstName = self.firstName
        Person.currentObjLastName = self.lastName
        Person.currentObjAge = self.age
        return self
    }  

    func copy(firstName firstName: String = Person.currentObjFirstName, 
              lastName: String? = Person.currentObjLastName,
              age: Int = Person.currentObjAge) -> Person {
        return Person(firstName: firstName, lastName: lastName, age: age)              
    }  

}

Example usage: 用法示例:

let foo = Person(firstName: "foo", lastName: "bar", age: 42)
let bar = foo.prepareCopy().copy(age: 21)
print(bar) // Person(firstName: "foo", lastName: Optional("bar"), age: 21)
let baz = foo.prepareCopy().copy(lastName: nil)
print(baz) // Person(firstName: "foo", lastName: nil, age: 42)

Possibly this solution goes under your description as "... boilerplate to construct a new struct passing in all those fields again" , though, and apart from that, prepareCopy() above isn't very pretty... 可能这个解决方案在你的描述中作为“...样板来构造一个新的结构再次传递到所有那些领域” ,但除此之外,上面的prepareCopy()不是很漂亮......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM