你如何在Swift中复制对象?

时间:2015-01-27 15:51:46

标签: swift copy

我有以下课程:

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)

如何以适当的年龄创建wrongClient的新版本?

我想要以下内容:

let rightClient = Client(wrongClient, age: 42)

例如,OCaml允许开发人员执行以下操作:

type client = {
  name : string;
  age : int;
}

let wrong_client = {name = "John"; age = 25}
let right_client = {wrong_client with age = 42}

或者在Scala中:

case class Client(name: String, age: Int)

val wrongClient = Client(name: "John", age: 9)
val rightClient = wrongClient.copy(age=42)

修改

我想尝试使用Swift进行数据不变性和数据共享。

因为不可变数据意味着"生成"其他值的值,"复制"对象经常发生。所以我的问题是:如何使用Swift轻松地从其他对象构造新对象?

编辑2

我目前正在关注Swiftz' lenses

6 个答案:

答案 0 :(得分:3)

您可以将客户端实现为struct而不是class,因为struct始终按值传递。

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

将wrongClient分配给rightClient会创建一个副本。当您更新rightClient的age时,wrongClient仍然是18.

答案 1 :(得分:1)

您可以添加其他init方法。

   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)
   }

答案 2 :(得分:1)

没有任何明确的简写。我建议像:

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)

答案 3 :(得分:1)

必须有更好的方法,但我目前的解决方案是:

   init(name: String, age: Int) {
       self.name = name
       self.age = age
   }

   init(from: Client, name: Int? = nill, age: Int? = nil) {
       self.name = name ?? Client.name
       self.age = age ?? Client.age
   }

答案 4 :(得分:0)

如果您需要数组的副本,只需使用过滤器并使用总是如下的内容:

let oldTagValueKey = self.tagValueKey.filter({ $0.value.characters.isEmpty == false })

答案 5 :(得分:0)

  1. 使您的类符合 NSCopying。这不是严格要求的, 但它使您的意图明确。
  2. 实现方法 copy(with:),实际复制发生的地方。
  3. 对您的对象调用 copy()。

以下是一个完全符合 NSCopying 协议的 Person 类示例:

class Person: NSObject, NSCopying {

  var firstName: String
  var lastName: String
  var age: Int

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

  func copy(with zone: NSZone? = nil) -> Any {
    let copy = Person(firstName: firstName, lastName: lastName, age: age)
    return copy
  }

注意 copy(with:) 是通过使用当前人的信息创建一个新的 Person 对象来实现的。

完成后,您可以像这样测试您的复制:

let paul = Person(firstName: "Paul", lastName: "Hudson", age: 36)
let sophie = paul.copy() as! Person

sophie.firstName = "Sophie" sophie.age = 6

print("\(paul.firstName) \(paul.lastName) is \(paul.age)")
print("\(sophie.firstName) \(sophie.lastName) is \(sophie.age)")

来源:https://www.hackingwithswift.com/example-code/system/how-to-copy-objects-in-swift-using-copy