Swift 可选项的本质、 运算符重载 、扩展
类、结构体、枚举可以为现有的运算符提供自定义的实现,这个操作叫做运算符重载
重载:函数名相同,功能不同
func sum(v1, v2)
func sum(v1, v2, v3)
/// 点
struct Point{
var x = 0, y = 0
static func + (p1: Point, p2: Point) -> Point {
print("p1: \(p1) + p2: \(p2)的操作")
return Point(x: p1.x + p2.x, y: p1.y + p2.y)
}
static func - (p1: Point, p2: Point) -> Point {
print("p1: \(p1) - p2: \(p2)的操作")
return Point.init(x: p1.x - p2.x, y: p1.y - p2.y)
}
static prefix func - (p: Point) -> Point{
return Point(x: -p.x, y: -p.y)
}
static func += (p1: inout Point, p2: Point){
p1 = p1 + p2
}
static prefix func ++ (p: inout Point) -> Point {
p += Point(x: 1, y: 1)
return p
}
static postfix func ++ (p: inout Point) -> Point {
let temp = p
p += temp
return temp
}
static func == (p1: Point, p2: Point) -> Bool {
p1.x == p2.x && p1.y == p2.y
}
}
//重载(结合性)
var p1 = Point.init(x: 1, y: 1)
var p2 = Point.init(x: 2, y: 2)
var p3 = Point.init(x: 3, y: )
var p4 = p1 + p2 + p3
print(p4)
Equatable 等价性
要想得知2个实例是否等价,一般的做法是遵守Equable协议,重载 == 运算符
与此同时,等价于重载了!=
Swift为以下类型提供默认的Equatable 实现
没有关联类型的枚举 (关联类型中不确定比较什么)
class Cat{}
enum Answer{
case wrong(Cat)
case right
}
只拥有遵守Equatable 协议关联类型的枚举
enum Answer: Equatable{
case wrong(Int) //Int 本身遵守Eqautable
case right
}
只拥有遵守Equatable 协议存储属性的结构体
引用类型比较存储的地址值是否相等(是否引用这同一个对象),
使用恒等运算符
=== 、!==
var p1 = Person(age: 10)
var p2 = Person(age: 10)
print(p1 === p2)//比较地址值
Comparable 比较大小
相比较2个实例的大小,一般的做法是:
1、遵守Comparable 协议
2、重载相应的运算符
//score 大的比较大,若score相等,age小的比较大
struct Student: Comparable{
var age: Int
var score: Int
init(score: Int, age: Int){
self.age = age
self.score = score
}
static func < (lhs: Student, rhs: Student) -> Bool {
(lhs.score < rhs.score) || ( lhs.score == rhs.score && lhs.age > rhs.age)
}
static func > (lhs: Student, rhs: Student) -> Bool{
(lhs.score > rhs.score) || (lhs.score == rhs.score && lhs.age < rhs.age)
}
static func <= (lhs: Student, rhs: Student) -> Bool {
!(lhs > rhs)
}
static func >= (lhs: Student, rhs: Student) -> Bool {
!(lhs < rhs)
}
}
自定义运算符(Custom Operator)
可自定义新的运算符:在全局作用域使用operator 进行声明
prefix operator 前缀运算符
postfix operator 后缀运算符
infix operator 中缀运算符 : 优先级组
precedemcegroup 优先级组 {
associativity: 结合性(left\right\none)
higherThan: 比谁的优先级高
lowerThan: 比谁的优先级低
assignment: true 代表可选链操作中拥有跟赋值运算符一样的优先级 (如果是赋值运算符怎么思考)
}
扩展(Extension)
Swift 中的扩展,有点类似与OC中的分类 (Category)
扩展可以为枚举、结构体、类、协议添加新功能
可以添加方法、计算属性、下标、(便捷)初始化器、嵌套类型、协议等等
扩展不能办到的功能
1、不能覆盖原有功能
2、不能添加存储属性,不能向已有的属性添加属性观察器
3、不能添加父类
4、不能添加指定初始化器(init),添加反初始化器(deinit)
- 如果希望自定义初始化器的同时,编译器也能生成默认的初始化器
- 可以 在 扩展 中编写自定义初始化器,
- 类遵守协议实现的require初始化器,不能写在扩展中
- 类 的扩展中可以增加便捷初始化器
- require 初始化器也不能写在扩展中
协议 给协议添加扩展
如果一个类型已经是吸纳了协议的所有要求,但是还没有声明它遵守了这个协议
可以通过扩展来让它遵守这个协议
- 扩展可以给协议提供默认实现,也间接实现【可选协议】的效果 (协议的默认所有的方法必须实现)
- 扩展可以给协议扩充【协议中从未声明过的方法】static 类方式也可以
- 类的实例调用的时候也是调用的扩展中的实现
泛型
扩展中依然可以使用原类型中的泛型类型
符合条件才扩展
extension Stack : Equatable where E : Equatable {
}