How do you copy objects in Swift?
Solution 1
You can implement Client as a struct
instead of a class
since struct
is always passed by value.
struct Client {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
var wrongClient = Client(name: "John", age: 18)
var rightClient = wrongClient
rightClient.age = 99
Assigning wrongClient to rightClient creates a copy. When you update the age
of rightClient, wrongClient still remains 18.
Solution 2
There isn't any defined short-hand for it. I'd recommend something like:
class Client {
let name: String
let age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
private init(from: Client, age:Int) {
self.name = from.name
self.age = age
}
func withAge(age:Int) -> Client {
return Client(from: self, age: age)
}
}
let right_client = Client(name: "John", age: 9)
let wrong_client = right_client.withAge(42)
Solution 3
There has to be a better way, but my current solution is this:
init(name: String, age: Int) {
self.name = name
self.age = age
}
init(from: Client, name: Int? = nil, age: Int? = nil) {
self.name = name ?? Client.name
self.age = age ?? Client.age
}
Solution 4
You could add another init
method.
required init(name: String, age: Int) {
self.name = name
self.age = age
}
convenience init(from: Client, withAge: Int) {
self.init(name: from.name, age: withAge)
}
Solution 5
In our Swift code generator we automatically include a copy constructor for every class. The generator is here: https://github.com/eclipse/agileuml
An example of the constructor, working with inheritance, is:
class Person
{ init() { }
init(copyFrom: Person) {
self.name = copyFrom.name
self.age = copyFrom.age
self.parents = copyFrom.parents
}
func copy() -> Person
{ let res : Person = Person(copyFrom: self)
return res
}
var name : String = ""
var age : Int64 = 0
var parents : [Person] = []
}
class Staff : Person
{ override init()
{ super.init() }
init(copyFrom: Staff) {
super.init(copyFrom: copyFrom)
self.staffNo = copyFrom.staffNo
self.boss = copyFrom.boss
}
override func copy() -> Staff
{ let res : Staff = Staff(copyFrom: self)
return res
}
var staffNo : Int = 0
var boss : [Staff] = []
}
Sequences, sets and maps are also copied element-by-element.
Related videos on Youtube
Antoine
Updated on September 14, 2022Comments
-
Antoine over 1 year
I have the following class:
class Client { let name: String let age: Int init(name: String, age: Int) { self.name = name self.age = age } } let wrongClient = Client(name: "John", age: 9)
How can I create a new version of
wrongClient
with the right age?I want something like the following:
let rightClient = Client(wrongClient, age: 42)
For example OCaml lets developers do the following:
type client = { name : string; age : int; } let wrong_client = {name = "John"; age = 25} let right_client = {wrong_client with age = 42}
Or in Scala:
case class Client(name: String, age: Int) val wrongClient = Client(name: "John", age: 9) val rightClient = wrongClient.copy(age=42)
EDIT
I want to experiment with data immutability and data sharing with Swift.
Because immutable data imply "generating" values from other values, "copying" objects can happen often. So my question really is : how can I easily construct new objects from other objects with Swift?
EDIT 2
I'm currently looking at Swiftz' lenses.
-
Antoine about 9 yearsIs there a way to automate this behaviour for every classes?
-
fred02138 about 9 yearsNot that I'm aware of.
-
Ali Aqdas about 3 yearsThanks for your answer it's working for me <3