前言
Swift
标准库为我们提供了55中协议,基本都是以Type
、able
、Convertible
结尾的。
以Type
结尾的协议,表示可以被当作某种类型;
以able
结尾的协议,表示具备某种能力或者特性;
以Convertible
结尾的协议,表示能够进行改变或者变化。
Swift标准库中的55个协议
AbsoluteValuable
AnyCollectionType
,
AnyObject
ArrayLiteralConvertible
BidirectionalIndexType
BitwiseOperationsType
BooleanLiteralConvertible
BooleanType
CVarArgType
CollectionType
Comparable
CustomDebugStringConvertible
CustomLeafReflectable
CustomPlaygroundQuickLookable
CustomReflectable
CustomStringConvertible
DictionaryLiteralConvertible
Equatable
ErrorType
ExtendedGraphemeClusterLiteralConvertible
FloatLiteralConvertible
FloatingPointType
ForwardIndexType
Generator Type
Hashable
Indexable
IntegerArithmeticType
IntegerLiteralConvertible
IntegerType
IntervalType
LazyCollectionType
LazySequenceType
MirrorPathType
MutableCollectionType
MutableIndexable
MutableSliceable
NilLiteralConvertible
OptionType
OutputStreamType
RandomAccessIndexType
RangeReplaceableCollectionType
RawRepresentable
ReverseIndexType
SequenceType
=> Sequence
SetAlgebraType
SignedIntegerType
SignedNumberType
Streamable
Strideable
StringInterpolationConvertible
StringLiteralConvertible
UnicodeCodecType
UnicodeScalarLiteralConvertible
UnsignedIntegerType
常见的协议
Equatable
Equatable
是比较相关的协议,遵循该协议表示实例能够用于做相等的比较,但是需要重载==
运算符。
struct Person: Equatable {
var name: String
var age: Int
static func == (lhs: Person, rhs: Person) -> Bool {
return lhs.name == rhs.name && lhs.age == rhs.age
}
}
Hashable
哈希表是一种基础的数据结构。Swift中字典由两种泛型类型组成,其中Key
必须实现Hashable
协议。
public protocol Hashable : Equatable {
var hashValue: Int { get }
func hash(into hasher: inout Hasher)
}
通过以上源码可以看出Hashable
是遵循了Equable
。
Comparable
Comparable
是基于Equatable
的一种延续,同样用于比较相关的协议,遵循该协议的实例能够进行比较,但是需要重载<
运算符。
struct Person: Comparable {
var name: String
var age: Int
static func < (lhs: Person, rhs: Person) -> Bool {
return lhs.age < rhs.age
}
}
CustomStringConvertible
CustomStringConvertible
提供了一种用文本表示一个对象或者结构的描述的方式,可以在任何遵循该协议的类型中自定义结构的文本,但是一定需要覆盖description
的属性。
struct Person: CustomStringConvertible {
var name: String
var age: Int
var description: String {
return "\(name)" + "的年龄是" + "\(age)"
}
}
ExpressibleByArrayLiteral
ExpressibleByArrayLiteral
提供了使用数组文本初始化的类型的能力,具体就是使用逗号分割的值、实例、字面值列表
struct Person: ExpressibleByArrayLiteral {
typealias ArrayLiteralElement = Any
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
init(arrayLiteral elements: Person.ArrayLiteralElement...) {
var name: String = ""
if let nm = elements.first as? String {
name = nm
}
var year: Int = 0
if let aage = elements[1] as? Int {
year = aage
}
self.init(name: name, age: year)
}
}
使用协议的好处
协议可以当作类型使用
苹果在Swift
中提出协议可以作为一种类型,并且在官方文档中还为开发者具体指出了可以将协议当作类型使用的具体场景:
- 作为常量、变量或者属性的类型
- 作为数组、字典或者其他存储器的元素类型
- 在函数、方法或者初始化容器里作为形参或者返回类型