[swift]MutableCollection vs RangeReplaceableCollection

标签: Swift
发布时间: 2017/3/6 22:52:03
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.

苹果的 MutableCollection API 参考:

MutableCollectionProtocol允许更改集合的元素的值,但不是集合本身的长度。需要添加或移除元素的操作,请参阅 RangeReplaceableCollection Protocol相反。

然而, MutableCollection 需要以下下标︰

subscript(bounds: Range<Self.Index>) -> Self.SubSequence { get set }

这不允许更改集合的长度?例如,不能空的范围与非空序列这个下标 setter 呢?

解决方法 1:

简短的回答︰

如果你有一个变量 MutableCollection 键入,然后你必须调用的下标 setter 只与一个范围和新的切片具有相同的长度。 符合某些类型 MutableCollection (如 Array ) 允许不同长度代替插入或删除元素,但在一般情况下,可变集合需要不允许的。

特别是,默认实现MutableCollection 下标二传手中止与运行时异常,如果范围和新的切片不具有相同的长度。

长远的答案︰

首先请注意,您不必执行

public subscript(bounds: Range<Index>) -> MutableSlice<Self>

在您自己的集合因为它有一个默认的实现Protocol扩展中。一个可以看到该方法的源代码中,下标 setter 调用

internal func _writeBackMutableSlice()

实现的功能在这里。 该函数首先将常见的元素数从扇区复制到目标区域,,然后验证的下标的范围,则新切片具有相同的长度︰

_precondition(
    selfElementIndex == selfElementsEndIndex,
    "Cannot replace a slice of a MutableCollection with a slice of a smaller size")
_precondition(
    newElementIndex == newElementsEndIndex,
    "Cannot replace a slice of a MutableCollection with a slice of a larger size")

所以你不能改变的长度 MutableCollection (默认值) 通过下标二传手,并试图这样做会终止该程序。

举个例子,让使用定义符合"最小"类型 MutableCollection :

struct MyCollection : MutableCollection, CustomStringConvertible {

    var storage: [Int] = []

    init(_ elements: [Int]) {
        self.storage = elements
    }

    var description: String {
        return storage.description
    }

    var startIndex : Int { return 0 }
    var endIndex : Int { return storage.count }

    func index(after i: Int) -> Int { return i + 1 }

    subscript(position : Int) -> Int {
        get {
            return storage[position]
        }
        set(newElement) {
            storage[position] = newElement
        }
    }
}

然后将集合的一部分替换一片长度相同的工作︰

var mc = MyCollection([0, 1, 2, 3, 4, 5])
mc[1 ... 2] = mc[3 ... 4]
print(mc) // [0, 3, 4, 3, 4, 5]

但对于不同的长度,它将中止与运行时异常︰

mc[1 ... 2] = mc[3 ... 3]
// fatal error: Cannot replace a slice of a MutableCollection with a slice of a smaller size

请注意,具体类型符合 MutableCollection 可能允许不同长度更换其下标的二传手,例如在 Array 做。

赞助商