繁体   English   中英

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

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

如果我有一个快速的结构

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

如果有一个对象a类型的Person ,不时地,仅该领域的一个改变,像lastName当人结婚,年龄当人过了一个生日等,但我并不想创建一个mutating func为每个字段,我也不想编写很多样板来构造一个新的结构,再次传递所有这些字段。 有没有比这更好的事情了

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

我知道这是一个非常简洁的scala与case类的功能,但我还没有看到swift中使用的这个功能。 我可以知道如何实现这一目标吗? 你们认为它应该是swift的特色吗? 也许我们可以提出一个快速的进化建议?

我不知道是否有一个优雅的解决方案。 一种选择是定义一个复制方法,该方法为每个属性采用可选参数,默认为当前属性值:

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)

Personcopy函数自然可以为其参数设置默认值,这样只允许使用person属性的子集调用它。 问题是我们可能不会使用self来指代我们希望默认使用的值。 但是,我们可以引用一个类的静态成员(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)              
    }  

}

用法示例:

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)

可能这个解决方案在你的描述中作为“...样板来构造一个新的结构再次传递到所有那些领域” ,但除此之外,上面的prepareCopy()不是很漂亮......

暂无
暂无

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

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