溢出运算符
目前的溢出运算符有三种&+ &- &*
var num:Int8 = 127
print(Int8.max) //127
print(Int8.min) //-128
num += 1
print(num) //抛出异常
正常做运算如果溢出就会报错,比如上述代码,Int8支持的最大数字是127,再加1就溢出了,系统会抛出异常,解决办法就是用溢出运算符&+
var num:Int8 = 127
print(Int8.max) //127
print(Int8.min) //-128
num &+= 1
print(num) //-128
加完之后的值,对256取余数,然后再减去256,比如128%256 - 256 = -128,如果是负数则加256, &- &*也同样是这个道理,最终的结果只能是[-128,127]这个区间的值
运算符重载
func +(_ dir:Dircetion,_ dir1:Dircetion) -> Dircetion
{
Dircetion(x: dir.x + dir1.x, y: dir.y + dir1.y)
}
struct Dircetion {
var x:Int
var y:Int
}
var dir = Dircetion(x: 10, y: 10) + Dircetion(x: 20, y: 20)
print(dir.x,dir.y) //30 30
基本的运算符重载,就是上述代码,比如可以重载个加号,实现结构体之间的加法运算
struct Dircetion {
var x:Int
var y:Int
static func +(_ dir:Dircetion,_ dir1:Dircetion) -> Dircetion
{
Dircetion(x: dir.x + dir1.x, y: dir.y + dir1.y)
}
}
struct Person {
var age:Int
static func +(_ person1:Person,_ person2:Person) -> Int
{
person1.age + person2.age
}
}
var dir = Dircetion(x: 10, y: 10) + Dircetion(x: 20, y: 20)
print(dir.x,dir.y) //30 30
var totalAge = Person(age: 10) + Person(age: 30)
print(totalAge) //40
当然这种重载最好写在各自的结构体内部,这样不管从调用还是查看代码都要清晰的多
前缀运算符和后缀运算符
struct Dircetion:CustomStringConvertible {
var x:Double = 0.0
var y:Double = 0.0
var description: String
{
String(format: "x:\(self.x) y:\(self.y)")
}
static let offset_x:Double = 0.01
static let offset_y:Double = 0.01
static prefix func ++(_ dir:inout Dircetion) -> Dircetion
{
dir.x += self.offset_x
dir.y += self.offset_y
return dir
}
static postfix func ++(_ dir:inout Dircetion) -> Dircetion
{
let temp = dir
dir.x += self.offset_x
dir.y += self.offset_y
return temp
}
}
var dir:Dircetion = Dircetion(x: 10, y: 10)
let result = ++dir
let result1 = dir++
print(result) //x:10.01 y:10.01
print(result1) //x:10.01 y:10.01
print(dir) //x:10.02 y:10.02
prefix就是前缀postfix就是后缀运算符,都是修饰的++,可以看到result和result1的输出结果是一样的,因为result1调用的是后缀,后缀会先赋值再计算,所以result1还是没加之前的dir
比较运算符
Equatable协议
Equatable协议的目的就是判断是否相等
struct Person :Equatable {
var userID:String = ""
var name:String = ""
}
var p1 = Person(userID: "12345",name: "张三")
var p2 = Person(userID: "12345",name: "张大壮")
print(p1 == p2) //false
一般继承了Equatable系统会生成一个比较方式,类除外,类必须自己写,但这个是可以自定义的,和运算符重载一毛一样
struct Person :Equatable {
var userID:String = ""
var nickName:String = ""
static func ==(_ p1:Person,_ p2:Person) -> Bool {
p1.userID == p2.userID
}
}
var p1 = Person(userID: "12345",nickName: "蛋蛋的哀伤")
var p2 = Person(userID: "12345",nickName: "惜雨")
print(p1 == p2) //true
比如上述代码,重载了==,只比较userID,哪怕是两个不同的Person类,但userID是一样的,就默认是一个用户,然后可以做些摒弃之类的操作,
Equatable在枚举和结构体系统是会生成一个默认的==符号重载,但类是必须自定义的,如果没有继承Equatable协议的结构体,枚举,类
Comparable协议
比较运算符,和==类似,不过区别是> < >= <=这些,就不赘述了和==的重载方式一样,需要自定义,内容想咋写咋写,只要能编译过
自定义运算符
infix operator <<<
func <<<(_ v1:inout Int,_ v2:Int) -> Int{
(v1 << v2) << v2
}
var v1:Int = 1
print((v1 <<< 4)) //256
基础的自定义运算符,就是这样,其中 infix 代表中缀,就是放中间的,一般中缀可以传递左右两个参数,前缀(prefix)和后缀(postfix)只能传递一个参数,还写一个运算符的定义组,后面的运算符遵守这个组,则默认设置组里面的参数,类似一种自定义运算符的配置文件,定义运算符的优先级,使用方式等等
直接截图吧,懒得一个个敲了,定义方式和前面一样,只是多了个级组来设置各种