[英]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. Person
的copy
函数自然可以为其参数设置默认值,这样只允许使用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.