在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Swift中,大量内置类如Dictionary,Array,Range,String都使用了协议 先看看Hashable哈希表是一种基础的数据结构.,Swift中字典具有以下特点:字典由两种范型类型组成,其中 key 必须实现 Hashable 协议.关于 swift 中字典是怎么实现的,可以看这篇 . public protocol Hashable : Equatable { public var hashValue: Int { get } }
可以看到 Hashable遵循了 Equable,那再来看看 Equable public protocol Equatable { public func ==(lhs: Self, rhs: Self) -> Bool }
看来遵循 Equable 都必须重载这个 == ,来定义自己的判等方法. struct MyPoint: Hashable, Comparable { var x: Int var y: Int var hashValue: Int { get { return x.hashValue + y.hashValue } } } func ==(lhs: MyPoint, rhs: MyPoint) -> Bool { return lhs.hashValue == rhs.hashValue } let pointA = MyPoint(x: 1, y: 1) let pointB = MyPoint(x: 1, y: 1) let pointC = MyPoint(x: 1, y: 2) pointA == pointB //true pointA == pointC //false
如果需要比较大小需要遵循 Comparable这个协议,协议需要内容就不贴了,直接上 code: func <(lhs: MyPoint, rhs: MyPoint) -> Bool { return lhs.hashValue < rhs.hashValue } func <=(lhs: MyPoint, rhs: MyPoint) -> Bool { return lhs.hashValue <= rhs.hashValue } func >(lhs: MyPoint, rhs: MyPoint) -> Bool { return lhs.hashValue > rhs.hashValue } func >=(lhs: MyPoint, rhs: MyPoint) -> Bool { return lhs.hashValue >= rhs.hashValue } pointA >= pointB //true pointA > pointC //false pointA < pointC //true
借用 Mattt的话来做下总结:
再看看Sequence (这部分 Swift3有变化)SequenceType(Swift 2.x) -> Sequence (Swift 3.0)SequenceType在喵神的 Swifttips 里面已经讲解的很好了,我还是把自己的例子写了下来.这部分代码是 Swift3版本下的. public protocol SequenceType { associatedtype Iterator : IteratorProtocol //在3.0以前是GeneratorType ........ }
IteratorProtocol又是什么呢?其实GeneratorType一样,可以理解为生成器 public protocol IteratorProtocol { associatedtype Element public mutating func next() -> Self.Element? }
associatedtype Element要求实现这个协议的类必须定义一个名为Element的别名,这样一定程度上实现了泛型协议。协议同时要求实现next函数,其返回值是别名中定义的Element类型,next函数代表生成器要生成的下一个元素。 struct Book { var name: String = "" var price: Float = 0.0 init(name: String, price: Float) { self.name = name self.price = price } }//定义一个 Book 的 Struct, 有书名和价格 class BookListIterator: IteratorProtocol { typealias Element = Book //将 Book 类赋值 Element var currentIndex: Int = 0 var bookList: [Book]? init(bookList: [Book]) { self.bookList = bookList } //初始化方法 //用来遍历 bookList,直到返回 nil func next() -> BookListIterator.Element? { guard let list = bookList else { return nil } if currentIndex < list.count { let element = list[currentIndex] currentIndex += 1 return element } else { return nil } } }
现在IteratorProtocol这个生成器已经写好了,可以写 Sequence了 class BookList: Sequence { var bookList: [Book]? init() { self.bookList = [Book]() } func addBook(book: Book) { self.bookList?.append(book) } // associatedtype Iterator : IteratorProtocol typealias Iterator = BookListIterator //public func makeIterator() -> Self.Iterator func makeIterator() -> BookList.Iterator { return BookListIterator(bookList: self.bookList!) } }
来试试写的 BookList: let bookList = BookList() bookList.addBook(book: Book(name: "Swift", price: 12.5)) bookList.addBook(book: Book(name: "iOS" , price: 10.5)) bookList.addBook(book: Book(name: "Objc", price: 20.0)) for book in bookList { print("\(book.name) 价格 ¥\(book.price)") } // Swift 价格 ¥12.5 // iOS 价格 ¥10.5 // Objc 价格 ¥20.0
而且不止可以使用 for...in, 还可以用 map , filter 和 reduce. 从 Sequence 到 CollectionSequenceType(Swift 2.x) -> Sequence (Swift 3.0)如果现在我们要看 bookList的 count, 就牵扯到了Collection这个协议,可以发现这个协议是对Indexable 和 Sequence 的扩展. 重点看看这个Indexable在2.x的时候,Indexable 并没有继承任何其他协议,那么3.0来了,来了个IndexableBase:
那再来看IndexableBase: //2.x版本indexable var endIndex: Self.Index var startIndex: Self.Index subscript(_: Self.Index) //新增的下标以及实例方法 subscript(_: Range<Self.Index>) func formIndex(after:) func index(after:)
再回到 Collection, 如果我们的类型已经遵循了Sequence,那么就只需要遵循: var startIndex: Int
var endIndex: Int
subscript(_: Self.Index)
func index(after:)
这四个需求中,startIndex和endIndex是为了 Collection 中要遵循 Indexable协议,还得实现一个下标索引来获取对应索引元素.在 Swift3中,还需要声明 index(after:),关于这个戳swift-evolutionl链接. extension BookList: Collection { typealias Element = Book var startIndex: Int { return 0 } var endIndex: Int { return bookList!.count } subscript(i: Int) -> Element { precondition((0..<endIndex).contains(i), "index out of bounds") return bookList![i] } func index(after i: Int) -> Int { if i < endIndex { return i + 1 } else { return endIndex } } }
是几个属性方法的实现还是挺简单的,现在BookList 这个 class,既遵循了 Sequence 和 Collection, 就有超过40种方法和属性可以使用: booklist.first //(Book(name: "Swift", price: 12.5)) booklist.count // 3 booklist.endIndex // 3 booklist.isEmpty //false
现在自己创建的类型就已经遵循了 Sequence和 Collection,还有map,reduce 等函数式方法可以使用. |
请发表评论