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 等函数式方法可以使用.

从Swift3的标准库协议看面向协议编程(一)的更多相关文章

  1. python第六天 函数 python标准库实例大全

    今天学习第一模块的最后一课课程--函数: python的第一个函数: 1 def func1(): 2 print('第一个函数') 3 return 0 4 func1() 1 同时返回多种类型时, ...

  2. Swift中面向协议的编程

    什么是面向协议的编程? 面向协议的编程,是一种编程范式. 编程范式,是一个计算机科学用语.维基百科中的解释是,计算机编程的基本风格或典型模式.通俗来说,就是解决某一个问题的方法不同方法和思路. 像大家 ...

  3. Android 面向协议编程 体会优雅编程之旅

    Android中面向协议编程的深入浅出 http://blog.csdn.net/sk719887916/article/details skay编写 说起协议,现实生活中大家第一感觉会想到规则或者约 ...

  4. python:模块1——标准库简介

    一.文档 windows系统:IDLE中打开帮助文档 Tutorial:简单入门 Library Reference:python内置函数和标准库(看不完的,当做字典来查)(此外还有pypi(拍派社区 ...

  5. AOP 面向切面编程

    AOP http://blog.csdn.net/xiang_j2ee/article/details/6851963 Android 支持 AspectJ 这个库来实现面向切面编程. 使用 Apac ...

  6. 造轮子 | 怎样设计一个面向协议的 iOS 网络请求库

    近期开源了一个面向协议设计的网络请求库 MBNetwork,基于 Alamofire 和 ObjectMapper 实现,目的是简化业务层的网络请求操作. 须要干些啥 对于大部分 App 而言,业务层 ...

  7. php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便)

    php spl标准库简介(SPL是Standard PHP Library(PHP标准库)(直接看代码实例,特别方便) 一.总结 直接看代码实例,特别方便易懂 thinkphp控制器利眠宁不支持(说明 ...

  8. C++ 标准库概览(一分钟就看完了)

    C++ 标准库以若干头文件的方式提供. 下面简单介绍一个各头文件的内容. 第一部分 容器 Containers <array> C++11 新增.提供了容器类模板 std::array,固 ...

  9. fir.im Weekly - 揭秘 iOS 面向协议编程

    本期 fir.im Weekly 重点推荐关于 iOS 面向协议编程相关文章,还有 iOS 多线程安全.Swift 进阶.Android MVVM 应用框架.Android 蓝牙实践等技术文章分享和工 ...

随机推荐

  1. Power BI for Office 365(六)Power Map简介

    如果说Power BI中最给力的功能是什么,我觉得是Power Map.Power Map第一次是出现在SQL Server 2014的新特性里被提及,前身就是GeoFlow.在Power Map下可 ...

  2. singleton pattern的推荐实现

    一.单例模式的C#实现: (1)使用double-checked locking的方式: public sealed class Singleton { private static volatile ...

  3. Javassist 字节码操作

    1.读写字节码 Javassist是用来处理java字节码的类库.字节码保存在二进制文件中称为类文件.每个类文件夹包括一个java类或接口. Javasssist.CtClass这个类是一个类文件的抽 ...

  4. amd和CMD

    AMD(Modules/Asynchronous-Definition).CMD(Common Module Definition)规范区别? Asynchronous Module Definiti ...

  5. iOS导航控制器常用函数与navigationBar常用属性

    导航控制器常用函数触发时机 当视图控制器的View将要出现时触发 - (void)viewWillAppear:(BOOL)animated 当视图控制器的View已经出现时触发 - (void)vi ...

  6. Subsonic的使用之基本语法、操作(2)

    查询 SubSonic2.1版本 – 例出3种查询. Product product = new Select().From<Product>() .Where(Product.Produ ...

  7. react学习小结(生命周期- 实例化时期 - 存在期- 销毁时期)

    react学习小结   本文是我学习react的阶段性小结,如果看官你是react资深玩家,那么还请就此打住移步他处,如果你想给一些建议和指导,那么还请轻拍~ 目前团队内对react的使用非常普遍,之 ...

  8. Unity Lightmap动态加载研究

    什么情况下需要Lightmap? 移动平台上目前暂时还不能开实时光影效果,会卡成幻灯片.所以就需要将光影烘焙到贴图上. 什么情况下需要动态加载Lightmap? 1.当项目抛弃了Unity的多场景模式 ...

  9. BZOJ1097: [POI2007]旅游景点atr

    ..k次最短路后,考虑如何满足先走一些点 用状压dp,每一个点考虑它所需要经过的点a[i],当当前走过的点包含a[i]时,i 这个点才可以到达. 写的时候用记忆化搜索. #include<bit ...

  10. DOM相关属性,方法,兼容性问题处理小析

    DOM:Document Object Model文档对象模型,用于让程序(js)取操作页面中的元素.DOM节点类型有12种. (一)属性 一.子节点操作1.所有子节点(1)元素.childNodes ...