运算符重载(Operator Overload)
- 类、结构体、枚举可以为现有的运算符提供自定义的实现,这个操作:运算符重载
struct Point{
var x = 0,y = 0
static func + (p1:Point,p2:Point) -> Point {
Point(x:p1.x +p2.x,y:p1.y + p2.y)
}
static func - (p1:Point,p2:Point) -> Point {
Point(x:p1.x - p2.x,y:p1.y - p2.y)
}
static prefix func - (p:Point) -> Point {
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 tmp = p
p += Point(x:1,y:1)
return tmp // 先返回旧值,再执行++
}
static func == (p1:Point,p2:Point) -> Bool {
(p1.x == p2.x) && (p1.y == p2.y)
}
}
var p1 = Point(x:10,y:20)
var p2 = Point(x:10,y:22)
let p3 = p1 + p2
print(p3)
Equatable
要想得知2个实例是否等价,一般做法是遵守Equatable 协议,重载 == 运算符
class Person : Equatable {
var age:Int
init(age:Int){
self.age = age
}
// 实现了 == ,就相当于 实现了 !=
static func == (lhs:Person,rhs:Person) -> Bool {
lhs.age == rhs.age
}
}
var p1 = Person(age:10)
var p2 = Person(age:10)
print(p1 == p2)
print(p1 != p2)
func eqauls<T:Equatable>(_ t1:T,_t2:T) -> Bool {
t1 == t2
}
- Swift为以下类型提供默认的Equatable实现
- 没有关联类型的枚举
enum Answer {
case wrong
case right
}
var s1 = Answer.wrong
var s2 = Answer.right
print(s1 == s2)
- 只拥有遵守Equatable协议关联类型的枚举
enum Answer: Equatable{
case wrong(Int) // Int 遵守Equatable协议
case right
}
var s1 = Answer.wrong(10)
var s2 = Answer.right(10)
print(s1 == s2) // true
enum Answer: Equatable{
case wrong(Int,String) // Int,String 遵守Equatable协议
case right
}
var s1 = Answer.wrong(10,"Jack")
var s2 = Answer.right(10,"Rose")
print(s1 == s2) // false 10 == 10,"Jack" != "Rose"
class Cat {}
enum Answer: Equatable{
case wrong(Int,String,Cat) // Int,String 遵守Equatable协议,Cat 不是遵守Equatable协议
case right
}
var s1 = Answer.wrong(10,"Jack")
var s2 = Answer.right(10,"Rose")
print(s1 == s2) // false 10 == 10,"Jack" != "Rose"
- 只拥有遵守Equatable协议存储属性的结构体
struct Point:Equatable{
var x = 0,y = 0
}
var p1 = Point(x:10,y:20)
var p2 = Point(x:10,y:20)
print(p1 == p2)
- 引用类型比较存储的地址值是否相等(是否引用着同一个对象),使用恒等运算符 ===、!==
class Person : Equatable {
var age:Int
init(age:Int){
self.age = age
}
// 实现了 == ,就相当于 实现了 !=
static func == (lhs:Person,rhs:Person) -> Bool {
lhs.age == rhs.age
}
}
var p1 = Person(age:10)
var p2 = Person(age:10)
var p3 = p1
print(p1 === p3) // true
print(p1 === p2) // false
Comparable
要想比较2个实例的大小,一般做法是:
- 遵守Comparable协议
- 重载相应的运算符
// score大的比较大,若score相等,age小的比较大
struct Student:Comparable{
var age:Int
var score:Int
init(score:Int,age:Int){
self.score = score
self.age = 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.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)
}
}
var stu1 = Student(score:100,age:20)
var stu2 = Student(score:98,age:18)
var stu3 = Student(score:100,age:20)
print(stu1 > stu2) // true
print(stu1 >= stu2) // true
print(stu1 >= stu3) // true
print(stu1 <= stu3) // true
print(stu2 < stu1) // true
print(stu2 <= stu1) // true
自定义运算符(Custom Operator)
可以自定义新的运算符:在全局作用域使用operator进行声明
- prifix operator 前缀运算符
- postfix operator 后缀运算符
- infix operator 中缀运算符:优先级组