可选项的本质是enum类型
本质是一致的
var age: Int? = 10
age = 20
age = nil
var age1: Optional<Int> = Optional<Int>.some(10)
age1 = .some(20)
age1 = .none
var age2 = Optional.some(10)
var age3 = Optional(10)
age = nil
age1 = .none
var age4 = Optional<Int>.none
非nil 和 nil
switch age {
case let v?:
print(v)
case nil:
print("2")
}
switch age {
case let .some(v):
print(v)
case .none:
print("2")
}
溢出运算符
Swift的算数运算符出现溢出时会抛出运行时错误
Swift有溢出运算符(&+ &- &*)用来支持溢出运算
溢出运算符 保证你溢出的值还在这个范围内 就是 回旋
var v1 = uint8.max
var v2 = v1 &+ 1
0
var v1 = uint8.max
var v2 = v1 &* 2
254
运算符重载
类 结构体 枚举可以为现有的运算符提供自定义的实现 叫做运算符重载
方法一
struct Point {
var x = 0, y = 0
}
func + (p1: Point, p2: Point) -> Point{
return Point(x: p1.x + p2.x, y: p1.y + p2.y)
}
var p1 = Point(x: 10, y: 20)
var p2 = Point(x: 11, y: 22)
let p3 = p1 + p2
let p4 = p1 + p2 + p3
方法二
struct Point {
var x = 0, y = 0
static func + (p1: Point, p2: Point) -> Point{
return Point(x: p1.x + p2.x, y: p1.y + p2.y)
}
}
var p1 = Point(x: 10, y: 20)
var p2 = Point(x: 11, y: 22)
let p3 = p1 + p2
let p4 = p1 + p2 + p3
prefix 前缀 负数
static prefix func - (p: Point) -> Point{
return Point(x: -p.x, y: -p.y)
}
+=
static func + (p1: Point, p2: Point) -> Point{
return Point(x: p1.x + p2.x, y: p1.y + p2.y)
}
static func += (p1: inout Point, p2: Point) -> 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
}
Equatable
需要知道2个实例是否等价 一般是遵守Equatable协议 重载 == 运算符
与此同时 等价于重载了 != 运算符
class Person: Equatable {
var age = 0
init(age: Int) {
self.age = age
}
static func == (lhs: Person, rhs: Person) -> Bool {
return lhs.age == rhs.age
}
}
var p1 = Person(age: 10)
var p2 = Person(age: 12)
print(p1 == p2)
func equals<T: Equatable>(_ t1: T, _ t2: T) -> Bool {
return t1 == t2
}
为以下类型提供了默认的Equatable实现
1.没有关联类型的枚举
2.只拥有遵守Equatable协议关联类型的枚举
3.只拥有遵守Equatable协议存储属性的结构体
类的Equatable 方法一定要自己实现
引用类型比较存储的地址值是否相等(是否引用着同一个对象) 使用恒等运算符=== !==
=== 只适用于引用类型
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 {
return (lhs.score < rhs.score) || (lhs.score == rhs.score && lhs.age > rhs.age)
}
static func > (lhs: Student, rhs: Student) -> Bool {
return (lhs.score > rhs.score) || (lhs.score == rhs.score && lhs.age < rhs.age)
}
static func <= (lhs: Student, rhs: Student) -> Bool {
return !(lhs > rhs)
}
static func >= (lhs: Student, rhs: Student) -> Bool {
return !(lhs < rhs)
}
}
自定义运算符
在全局作用域使用operator进行声明
自定义运算符类型
prefix operator 前缀运算符
postfix operator 后缀运算符
infix operator 中缀运算符 优先级组
precedencegroup 优先级组 {
associativity: 结合性(left right none)
higherThan: 比谁的优先级高
lowerThan: 比谁的优先级低
assignment: true代表在可选链操作中拥有跟赋值运算符一样的优先级
}
定义前缀运算符
prefix operator +++
prefix func +++ (_ i: inout Int){
return i += 2
}
//定义中缀运算符
infix operator +- : PlusMInusPrecedence
//高于乘法的优先级 低于除法的优先级
precedencegroup PlusMInusPrecedence {
associativity: none 结合性没有 就表明不能连续出现这个运算符
higherThan: AdditionPrecedence 高于乘法的优先级
lowerThan: MultiplicationPrecedence 低于除法的优先级
assignment: true true代表在可选链操作中拥有跟赋值运算符一样的优先级 (也就是说当
只有左边的有值的时候 才会进行赋值操作)
}
struct Point {
var x = 0, y = 0
static func +- (p1: Point, p2: Point) -> Point {
return Point(x: p1.x + p2.x, y: p1.y - p2.y)
}
}
var p1 = Point(x: 10, y: 20)
var p2 = Point(x: 5, y: 15)
var p3 = p1 +- p2
例子.png
assignment: true代表在可选链操作中拥有跟赋值运算符一样的优先级 如果p是nil 那么后面的那个就不会初始化 运算也不会进行
扩展
扩展可以为枚举 结构体 类 协议添加新功能
- 可以添加方法 计算属性 下标 (便捷)初始化器 嵌套类型 协议等
扩展不能做到的事情
1.不能覆盖原的功能
2.不能添加存储属性 不能向已有的属性添加属性观察器
3.不能添加父类
4.不能添加指定初始化器 不能添加反初始化器
不能添加存储属性 会影响内存结构 扩展时不允许改变内存结构的
不能添加父类 有可能影响内存结构
反初始化器只能写在原来类里面 不能写在扩展里面
如果希望自定义初始化器的同时 编译器也能够生成默认初始化器 可以在扩展中编写自定义初始化器
类遵守协议实现的required初始化器 不能写在扩展中
required初始化器 不能写在扩展中
如果一个类已经实现了协议的所有要求 但是还没有声明它遵守了这个协议 可以通过扩展让他遵守这个协议
所有的整数都遵守BinaryInteger 协议
func isOdd<T: BinaryInteger>(_ i: T) -> Bool {
return i % 2 != 0
}
extension BinaryInteger {
func isOdd() -> Bool {
return self % 2 != 0
}
}
扩展可以给协议提供默认实现 也可以间接实现[可选协议]的效果
扩展可以给协议扩充[协议中从未声明过的方法]
protocol Runnable {
func run1()
}
extension Runnable {
func run3() {
}
func run1() {
}
}
class Person: Runnable {
}
如果调用的方法 在协议声明中是没有的 那么调用方法的时候,同时你这个实例还遵守了这个协议 那么就默认实例里面是没有这个方法的 直接去协议的扩展里面去找这个方法
网友评论