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 都必须重载这个 == ,来定义自己的判等方法.
上 sample:

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: , y: )
let pointB = MyPoint(x: , y: )
let pointC = MyPoint(x: , y: )
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的话来做下总结:

在 Swift 中,Equatable 是一个基本类型,由此也演变出了 Comparable 和 Hashable 两种类型。这三个一起组成了这门语言关于对象比较的核心元素。

再看看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函数代表生成器要生成的下一个元素。
sample 是来自链接,写的非常清楚,我这只是贴贴我的 playground

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 =
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 +=
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.
再谈谈 Swift3的变化,其实就是变了GeneratorType To IteratorProtocol,就是这么任性....

从 Sequence 到 Collection

SequenceType(Swift 2.x) -> Sequence (Swift 3.0)

如果现在我们要看 bookList的 count, 就牵扯到了Collection这个协议,可以发现这个协议是对Indexable 和 Sequence 的扩展.

重点看看这个Indexable

在2.x的时候,Indexable 并没有继承任何其他协议,那么3.0来了,来了个IndexableBase:

public protocol Indexable : 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链接.
再看看怎么对 Sample 例子中BookList遵循 Collection

extension BookList: Collection {

    typealias Element = Book

    var startIndex: Int {
return
} var endIndex: Int {
return bookList!.count
} subscript(i: Int) -> Element {
precondition((..<endIndex).contains(i), "index out of bounds")
return bookList![i]
} func index(after i: Int) -> Int {
if i < endIndex {
return i +
} else {
return endIndex
}
}
}

是几个属性方法的实现还是挺简单的,现在BookList 这个 class,既遵循了 Sequence 和 Collection, 就有超过40种方法和属性可以使用:

booklist.first //(Book(name: "Swift", price: 12.5))
booklist.count //
booklist.endIndex //
booklist.isEmpty //false

现在自己创建的类型就已经遵循了 Sequence和 Collection,还有map,reduce 等函数式方法可以使用.

最新文章

  1. 【BZOJ1623】 [Usaco2008 Open]Cow Cars 奶牛飞车 贪心
  2. 拨乱反正:DDD 回归具体的业务场景,Domain Model 再再重新设计
  3. 使用spring注解@Controller @Service @Repository简化配置
  4. 利用cubieboard设置samba打印服务器
  5. 国内优秀Android学习资源
  6. signtool
  7. 初学JDBC,调用存储过程
  8. 关于YARN的HA
  9. asp.net+swfupload 多图片批量上传(附源码下载)
  10. 基于appium的移动端自动化测试,密码键盘无法识别问题
  11. DOM操作 JS事件 节点增删改查
  12. abap method中的异常处理
  13. 用python将MSCOCO和Caltech行人检测数据集转化成VOC格式
  14. Docker三剑客之 Compose
  15. Linux 安装MySQL-python
  16. T48566 【zzy】yyy点餐
  17. Kaldi 安装
  18. redis的搜索组件 redis-search4j
  19. RocketMQ之NameServer学习笔记
  20. orcale 之 PL/SQL的游标

热门文章

  1. Android 笔记 day2 拨号器
  2. Knockout.js随手记(3)
  3. Andriod学习笔记1:代码优化总结1
  4. ArcGIS 10与ArcEngine 10安装及破解
  5. markdown 常用语法 (在macdown内使用正常)
  6. 【Oracle】oracle取最大值和最小值的几个方法汇总
  7. MongoDB-C#驱动基本操作
  8. 【python+mysql】在python中调用mysql出问题 ImportError: No module named MySQLdb.constants
  9. [canvas]利用canvas绘制自适应的折线图
  10. C fread