Swift中的集合类型协议

Swift中的集合类型协议,第1张

概述集合类型协议 1 Sequence协议 Sequence 协议是集合类型结构中的基础。一个序列 (sequence) 代表的是一系列具有相同类型的值,你可以对这些值进行迭代。 Sequence 协议提供了许多强大的功能,满足该协议的类型都可以直接使用这些功能。 如下是一个自定义实现Sequence的例子, Sequence协议提供很多功能, 其中必须实现的只有一个迭代器, 返回一个Iterator

集合类型协议

1 Sequence协议

Sequence 协议是集合类型结构中的基础。一个序列 (sequence) 代表的是一系列具有相同类型的值,你可以对这些值进行迭代。 Sequence 协议提供了许多强大的功能,满足该协议的类型都可以直接使用这些功能。 如下是一个自定义实现Sequence的例子,Sequence协议提供很多功能,其中必须实现的只有一个迭代器,返回一个IteratorProtocol迭代器即可,所有关于Sequence的遍历筛选变形都是通过迭代器来实现的. 要实现自己的迭代器只需返回遵守IteratorProtocol协议的一个对象或者结构体即可.

//Sequence协议必须实现的部分protocol Sequence {    associatedtype Iterator: IteratorProtocol    func makeIterator() -> Iterator}//菲波那切数列的Sequence实现方式struct FibsQueue: Sequence {    let number: Int    init(_ number: Int) {        self.number = number    }    typealias Iterator = FibsIterator    func makeIterator() -> FibsQueue.Iterator {        return FibsIterator(number)    }}
2 IteratorProtocol协议

列通过创建一个迭代器来提供对元素的访问。迭代器每次产生一个序列的值,并且当遍历序列时对遍历状态进行管理。在 IteratorProtocol 协议中唯一的一个方法是 next(),这个方法需要在每次被调用时返回序列中的下一个值。当序列被耗尽时,next() 应该返回 nil.

//“protocol IteratorProtocol {    associatedtype Element    mutating func next() -> Element?}/// “FibsIterator 迭代器可以产生一个斐波那契序列。它将记录接下来的两个数字,并作为状态存储,next 函数做的事情是为接下来的调用更新这个状态,并且返回第一个数。和之前的例子一样,这个迭代器也将产生“无穷”的数字,它将持续累加数字”struct FibsIterator: IteratorProtocol {    let number: Int    var index: Int = 0    init(_ number: Int) {        self.number = number    }    var state = (0,1)    mutating func next() -> Int? {        if index >= number {            return nil        }        index += 1        let fibNumber = state.0        state = (state.1,state.0+state.1)        return fibNumber    }    typealias Element = Int}
3 Collection协议

集合类型 (Collection) 指的是那些稳定的序列,它们能够被多次遍历且保持一致。除了线性遍历以外,集合中的元素也可以通过下标索引的方式被获取到。下标索引通常是整数,至少在数组中是这样。不过我们马上回看到,索引也可以是一些不透明值 (比如在字典或者字符串中),这有时候让使用起来不那么直观。集合的索引值可以构成一个有限的范围,它具有定义好了的开始和结束索引。也就是说,和序列不同,集合类型不能是无限的。

Collection协议是建立在Sequence协议上的. 除了从Sequence中集成了全部的方法以外,得益于可以获取指定位置的元素以及稳定迭代的保证,集合还获取了一些新的能力。比如 count 属性,如果序列是不稳定的,那么对序列计数将会消耗序列中的元素,这显然不是我们的目的。但是对于稳定的集合类型,我们就可以对其进行计数。

即使你用不到集合类型提供的这些特性,你依旧可以让你自己的序列满足 Collection 协议,这将告诉你的序列类型的使用者该序列是有限的,而且可以进行多次迭代。不过如果你只是想说明序列可以被多次迭代,但却必须去选一个合适的索引类型,确实会显得比较奇怪。在实现 Collection 协议时,最难的部分在于选取一个合适的索引类型来表达集合类型中的位置。这样设计的一个目的是,Swift 团队希望避免引入一个专门的可多次迭代序列的协议,因为它和 Sequence 拥有同样的要求,但是语义却不一致,这容易让用户感到迷惑。

//Collection协议,swift3,其中房噶和变量还是比较多的,但是很多都有了默认的实现,所以我们只需要实现少数几个即可protocol Collection: Indexable,Sequence {    associatedtype Iterator: IteratorProtocol = IndexingIterator<Self>    associatedtype SubSequence: IndexableBase,Sequence = Slice<Self>    associatedtype Indexdistance: SignedInteger = Int    associatedtype Indices: IndexableBase,Sequence = DefaultIndices<Self>        var first: Iterator.Element? { get }    var indices: Indices { get }    var isEmpty: Bool { get }    var count: Indexdistance { get }        func makeIterator() -> Iterator    func prefix(through position: Index) -> SubSequence    func prefix(upTo end: Index) -> SubSequence    func suffix(from start: Index) -> SubSequence    func distance(from start: Index,to end: Index) -> Indexdistance    func index(_ i: Index,offsetBy n: Indexdistance) -> Index    func index(_ i: Index,offsetBy n: Indexdistance,limitedBy limit: Index) -> Index?        subscript(position: Index) -> Iterator.Element { get }    subscript(bounds: Range<Index>) -> SubSequence { get }}

一个自定义实现FIFO队列的例子

//自定义一个队列//首先定义好队列到底是什么,我们可以用协议来描述队列是社么/// 一个能够将元素入队和出队的类型protocol Queue {    /// 在 `self` 中所持有的元素的类型    associatedtype Element    /// 将 `newElement` 入队到 `self`    mutating func enqueue(_ newElement: Element)    /// 从 `self` 出队一个元素    mutating func dequeue() -> Element?}//实现一个队列,FIFO队列,其中元素类型是`Element`struct FIFOQueue<Element>: Queue {    fileprivate var left: [Element] = []    fileprivate var right: [Element] = []    /// 将元素添加到队列最后    /// - 复杂度: O(1)    mutating func enqueue(_ newElement: Element) {        right.append(newElement)    }    /// 从队列前端移除一个元素    /// 当队列为空时,返回 nil    /// - 复杂度: 平摊 O(1)    mutating func dequeue() -> Element? {        if left.isEmpty {            left = right.reversed()            right.removeAll()        }        return left.popLast()    }}//遵守 Collection 协议extension FIFOQueue: Collection {    public var startIndex: Int { return 0 }    public var endindex: Int { return left.count + right.count }    public func index(after i: Int) -> Int {        precondition(i < endindex)        return i + 1    }    public subscript(position: Int) -> Element {        precondition((0..<endindex).contains(position),"Index out of bounds")        if position < left.endindex {            return left[left.count - position - 1]        } else {            return right[position - left.count]        }    }}//ExpressibleByArrayliteral协议extension FIFOQueue: ExpressibleByArrayliteral {    public init(arrayliteral elements: Element...) {        self.init(left: elements.reversed(),right: [])    }}
4 ExpressibleByArrayliteral协议

当实现一个类似队列这样的集合类型时,最好也去实现一下 ExpressibleByArrayliteral。这可以让用户能够以他们所熟知的 [value1,value2,etc] 语法创建一个队列。

extension FIFOQueue: ExpressibleByArrayliteral {    public init(arrayliteral elements: Element...) {        self.init(left: elements.reversed(),right: [])    }}

'Self' is only available in a protocol or as the result of a method in a class; ...

Reference: Swift进阶

总结

以上是内存溢出为你收集整理的Swift中的集合类型协议全部内容,希望文章能够帮你解决Swift中的集合类型协议所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1057304.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存