美文网首页
可选项本质 溢出运算符 运算符重载 Equatable Co

可选项本质 溢出运算符 运算符重载 Equatable Co

作者: 纳兰沫 | 来源:发表于2019-09-25 17:16 被阅读0次

    可选项的本质是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
    

    文档参考1
    文档参考2

    例子.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 {
      
    
    }
    

    如果调用的方法 在协议声明中是没有的 那么调用方法的时候,同时你这个实例还遵守了这个协议 那么就默认实例里面是没有这个方法的 直接去协议的扩展里面去找这个方法

    泛型

    35796055-6384-4F5C-8518-43B3FC43856A.png

    相关文章

      网友评论

          本文标题:可选项本质 溢出运算符 运算符重载 Equatable Co

          本文链接:https://www.haomeiwen.com/subject/goyiectx.html