深度复制数组,其中元素是自定义类的可选

时间:2018-08-10 08:47:51

标签: arrays swift copy swift4

首先:我无法在场景中使用结构。我知道默认情况下结构是“按值传递”。但在我的情况下,我确实需要类对象的“按引用传递”语义。

就像标题说的那样,我正在尝试深复制一个Array,该Array包含一个自定义类的可选对象。

对于自定义类对象的深层副本,我实现了以下协议:

protocol Copyable {
    init(instance: Self)
}

extension Copyable {
    func copy() -> Self {
        return Self.init(instance: self)
    }
}

现在我也有需要深度复制的自定义类对象数组。为此,我为Array编写了一个扩展,其中Element为Copyable,它看起来像这样并且正在工作:

extension Array where Element: Copyable {
    func clone() -> Array {
        var copiedArray = Array<Element>()
        for element in self {
            copiedArray.append(element.copy())
        }
        return copiedArray
    }
}

假设我有2个自定义类。第一个已经符合Copyable,看起来像这样:

class MySimpleObject: Copyable {

    let myString: String

    init() {
        self.myString = ""
    }

    required init(instance: MySimpleObject) {
        self.myString = instance.myString
    }
}

现在,我的第二个自定义类包含两个MySimpleObject数组(1个元素为MySimpleObject的数组是非可选的,而1个元素MySimpleObject是可选的数组。此类像这样:

class MyObject {

    var myArray = [MySimpleObject]()
    var myArrayWithOptionals = [MySimpleObject?]()
}

现在我希望MyObject符合Copyable,这是令我困惑的部分。首先,我尝试过这样(但这给了我一个错误,如注释中所示:

class MyObject: Copyable {

    var myArray = [MySimpleObject]()
    var myArrayWithOptionals = [MySimpleObject?]()

    required init(instance: MyObject) {
        self.myArray = instance.myArray.clone()
        self.myArrayWithOptionals = instance.myArrayWithOptionals.clone()       // Type 'MySimpleObject?' does not conform to protocol 'Copyable'
    }
}

这个错误对我来说很有意义。由于MySimpleObject?不等于MySimpleObject

然后我的第二次尝试是将另一个扩展写入Array,但是我不确定如何以正确的方式执行此操作:

extension Array where Element == Optional<Copyable> {
    func cloneOptional() -> Array {
        var copiedArray = Array<Element>()
        for element in self {
            copiedArray.append(element?.copy())
        }
        return copiedArray
    }
}

MyObject如下所示:但是我也遇到错误(再次在注释中显示)

class MyObject: Copyable {

    var myArray = [MySimpleObject]()
    var myArrayWithOptionals = [MySimpleObject?]()

    required init(instance: MyObject) {
        self.myArray = instance.myArray.clone()
        self.myArrayWithOptionals = instance.myArrayWithOptionals.cloneOptional()   // '[MySimpleObject?]' is not convertible to 'Array<Optional<Copyable>>'
    }
}

有人能提示我我需要的方向吗?我们将如何以正确的方式实现这一目标?

如果您以任何方式需要更多信息,请在评论中告诉我。

最好的问候

Teetz

1 个答案:

答案 0 :(得分:2)

对于可选元素的数组扩展,您似乎有一些错误的假设。您正在调用尚未声明的可选参数copy。只需确保Optional也符合Copyable,并且它在可选数组上与clone一起正常工作即可。

extension Optional: Copyable where Wrapped: Copyable {
    init(instance: Optional<Wrapped>) {
        if let instance = instance {
            self = Optional(instance.copy())
        } else {
            self = nil
        }
    }
}

总的来说,您的代码看起来像这样,

protocol Copyable {
    init(instance: Self)
}

extension Copyable {
    func copy() -> Self {
        return Self.init(instance: self)
    }
}

extension Optional: Copyable where Wrapped: Copyable {
    init(instance: Optional<Wrapped>) {
        if let instance = instance {
            self = Optional(instance.copy())
        } else {
            self = nil
        }
    }
}

extension Array where Element: Copyable {
    func clone() -> [Element] {
        var copiedArray = [Element]()
        for element in self {
            copiedArray.append(element.copy())
        }
        return copiedArray
    }
}

class MySimpleObject: Copyable {

    let myString: String

    init() {
        self.myString = ""
    }

    required init(instance: MySimpleObject) {
        self.myString = instance.myString
    }
}

class MyObject: Copyable {

    var myArray = [MySimpleObject]()
    var myArrayWithOptionals = [MySimpleObject?]()

    required init(instance: MyObject) {
        self.myArray = instance.myArray.clone()
        self.myArrayWithOptionals = instance.myArrayWithOptionals.clone()
    }
}