Swift中的协议
Swift中的常用协议
Equatable
Equatable
协议用于相等的比较,遵守这个协议后必须对==
运算符进行重载。
struct Record: Equatable {
var wins: Int
var losses: Int
}
func ==(left: Record, right: Record) -> Bool {
return left.wins == right.wins && left.losses == right.losses
}
let recordA = Record(wins: 10, losses: 5)
let recordB = Record(wins: 10, losses: 5)
recordA == recordB//true
recordA != recordB//false
重载==
之后,!=
也可以正常使用
Comparable
Comparable
协议用于比较,只需要重载<
就可以了
struct Record: Equatable, Comparable {
var wins: Int
var losses: Int
}
func ==(left: Record, right: Record) -> Bool {
return left.wins == right.wins && left.losses == right.losses
}
func <(left: Record, right: Record) -> Bool {
if left.wins != right.wins {
return left.wins < right.wins
}
return left.losses > right.losses
}
Record
遵守Comparable
协议,表示其是一个可比较的对象。
var team1Record = Record(wins: 10, losses: 3)
var team2Record = Record(wins: 8, losses: 5)
var team3Record = Record(wins: 8, losses: 8)
var records = [team1Record, team2Record, team3Record]
records.sort()
CustomStringConvertible
遵循CustomStringConvertible
协议,只需要实现一个计算型的属性description
struct Record: Equatable, Comparable, CustomStringConvertible {
var wins: Int
var losses: Int
var description: String {
return "WINS: " + String(wins) + " , LOSSES: " + String(losses)
}
}
这时print(team1Record)
输出的结果就为:WINS: 10 , LOSSES: 3
BooleanType
BooleanType
可以让一个类型被视为一个布尔值,需要覆盖一个boolValue
属性。
var boolValue: Bool {
return wins > losses
}
就可以这样使用if
语句:
if recordA {
}
同样可以让基本类型实现BooleanType
协议,这样就可以直接来进行布尔判断,如下:
extension Int: BooleanType {
public var boolValue: Bool {
return self != 0
}
}
var wins = 0
if !wins {
print("You never win!")
}
面向协议编程
运算符重载
内容来自Operator Overloading in Swift Tutorial
例如,重载+
运算符,使两个Int
型数组相加:
func +(left: [Int], right: [Int]) -> [Int] { // 1
var sum = [Int]() // 2
assert(left.count == right.count, "vector of same length only") // 3
for (key, v) in enumerate(left) {
sum.append(left[key] + right[key]) // 4
}
return sum
}
自定义运算符
定义一个自定义运算符有三步:
- Name your operator命名运算符
自定义的运算符可以是ASCII字符,如/, =, -, +, !, *, %, <, >, &, |, ^
,也可以是Unicode字符。 - Choose a type选择一个类型
在Swift中,可以定义binary
,unary
和ternary
运算符,即一元、二元、三目运算符。 - Assign precedence and associativity指定优先级和结合型
关键字:
operator
prefix
前缀运算符,比如 (取正+、取负- 、自增++、自减–)postfix
后缀运算符,比如(自增++、自减–),这两可以前缀也可以后缀infix
中缀,最常见二元运算precedence
优先级的意思,取值 0~255 ,纯数字,不可以带符号,下划线,指数e/p 表示associativity
结合性,可以是 left, right, 或者 none
如下,自定义运算符⊕
,使两个Int类型数组相加:
infix operator ⊕ { associativity left precedence 140 } // 1
func ⊕(left: [Int], right: [Int]) -> [Int] { // 2
var sum = [Int](count: left.count, repeatedValue: 0)
assert(left.count == right.count, "vector of same length only")
for (key, v) in enumerate(left) {
sum[key] = left[key] + right[key]
}
return sum
}
泛型运算符
如下,指定类型:
infix operator ⊕ { associativity left precedence 140 }
func ⊕<T>(left: [T], right: [T]) -> [T] { // 1
var minus = [T]()
assert(left.count == right.count, "vector of same length only")
for (key, v) in enumerate(left) {
minus.append(left[key] + right[key]) // 2
}
return minus
}
但是,会报错Could not find an overload for '+' that accepts the supplied arguments.
。由于不知道类型,Swift不知道怎样相加。
所以,一般的做法是,先定义一个协议,再扩展原有类型:
protocol Number { // 1
func +(l: Self, r: Self) -> Self // 2
}
extension Double : Number {} // 3
extension Float : Number {}
extension Int : Number {}
infix operator ⊕ { associativity left precedence 140 }
func ⊕<T: Number>(left: [T], right: [T]) -> [T] { // 4
var minus = [T]()
assert(left.count == right.count, "vector of same length only")
for (key, v) in enumerate(left) {
minus.append(left[key] + right[key])
}
return minus
}