JHHK

欢迎来到我的个人网站
行者常至 为者常成

14_1、可选项本质、运算符重载、扩展(一)

目录

可选项的本质

/// 一、可选项的本质
func optionalNature() -> Void {

    //1、可选项的本质是enum
    do{
        print("-------1----------")
        /**
         可选项的本质是enum类型
         public enum Optional<Wrapped> : ExpressibleByNilLiteral {
             case none
             case some(Wrapped)
             public init(_ some: Wrapped)
         }
        */
        
        var num1:Int? = nil
        num1 = 10
        print("num1:",String(describing: num1))//num1: Optional(10)
        
        var num2:Optional<Int> = Optional<Int>.none
        num2 = Optional<Int>.some(10)
        print("num2:",String(describing: num2))//num2: Optional(10)
        
        var num3:Int? = Optional<Int>.none
        num3 = Optional<Int>.some(10)
        print("num3:",String(describing: num3))//num3: Optional(10)
    }
  
    //2、可选项的本质是enum
    do{
        print("------2-------")
        var age: Int? = 10
        age = nil
        
        let age0: Optional<Int> = Optional<Int>.some(10)
        let age1: Optional = .some(10)
        let age2 = Optional.some(10)
        var age3 = Optional(10)
        age3 = .none
        
        //打印时 as Any 可消除警告
        print(age as Any,       // nil
              age0 as Any,      // Optional(10)
              age1 as Any,      // Optional(10)
              age2 as Any,      // Optional(10)
              age3 as Any,      // nil
              separator:"\n"
        )
        
        
        
        switch age {
        case Optional<Int>.none:
            print("none")   //none
        case Optional<Int>.some(let v):
            print("v = ",v)
        }
        
        
        switch age {
        case let v ://直接将age的值绑定到v 不会自动解包
            print(v as Any)// nil
        }
    }
    
    //3、可选项的本质是enum
    do{
        print("-------3---------")
        let age:Int? = 10
        switch age{
        case let .some(v)://关联值绑定
            print("some", v)    //some 10
        case .none:
            print("none")
        }
        
        
        switch age {
        case let v?://关联值绑定
            print("some", v)    //some 10
        case nil:
            print("none")
        }
        
        
        //等价于这种写法
        if let v = age {
            print(v)    //10
        }else{
            print("nil")
        }
    }
}

多重可选项的本质

/// 二、多重可选项的本质
func mutipleOptinal() -> Void {
    
    //1、可选项的本质就是带泛型的枚举
    do{
        print("-------1-------")
        let age1: Int? = 10
        var age2: Int?? = age1
        age2 = nil
        
        //上面写法等价于下面这种写法
        age2 = Optional.some(Optional.some(10))
        age2 = .none
        print(String(describing: age2))//nil
    }
    
    
    //2、可选项的本质就是带泛型的枚举
    do{
        print("-------2-------")
        var age1: Optional<Optional> = .some(.some(10))
        age1 = .none
        age1 = 10
        print(age1 as Any)//Optional(Optional(10))

        let age2: Int?? = 10
        print(age2 as Any)//Optional(Optional(10))
        
        let age3:Optional<Optional<Int>> = 20
        print(age3 as Any)//Optional(Optional(20))
    }
    
    
}

多重可选项的本质2

/// 三、多重可选项的本质2
func mutipleOptinal2() -> Void {
    do{
        print("--------1---------")
        let num1:Int? = nil
        let num2:Int?? = num1
        let num3:Int?? = nil
        
        print(num1 == num2)//true
        print(num1 == num3)//false
        print(num2 == num3)//false
    }
    
    
   
    do{
        print("--------2---------")
        let num1:Optional<Int>           =  Optional<Int>.none          //nil
        let num2:Optional<Optional<Int>> =  Optional<Int>.none          //相当于 num1 注意这里的类型区别
        let num3:Optional<Optional<Int>> =  Optional<Optional<Int>>.none//相当于 nil
        print(num1 == num2)//true
        print(num1 == num3)//false
        print(num2 == num3)//false
    }
    
    do{
        print("--------3---------")
        enum Test<T>{
            case none
            case some(x:T)
        }
        
//        let num1:Test<Int>       = Test<Int>.none       //nil
//        let num2:Test<Test<Int>> = Test<Int>.none       //num1 注意这里的类型区别
//        let num3:Test<Test<Int>> = Test<Test<Int>>.none //nil
//        print(num1,num2,num3,separator:"\n")
    }
    
    do{
        print("----------4---------")
        var num1:Optional<Int>           = 10   //.some(10)
        var num2:Optional<Optional<Int>> = 10   //.some(.some(10))
        var num3:Optional<Optional<Int>> = Optional<Optional<Int>>.some(10)
        //比较的时候然后会自动解包??
        print(num1 == num2)//true
        print(num1 == num3)//true
        print(num2 == num3)//true
        
        num1 = .none//Optional<Int>.none
        num2 = .none//Optional<Optional<Int>>.none
        num3 = .none//Optional<Optional<Int>>.none
        print(num1 == num2)//false
        print(num1 == num3)//false
        print(num2 == num3)//false
    }
}

看下图分析:

num1 == num3; // true 非空的可选项比较会递归解包
num2 == num4; // false 空也是有类型的,它俩类型不同所以不相等。   

这里重点介绍下num5,num5是非空的,所以比较时会递归解包
num2 == num5; // ture

溢出运算符

/// 四、溢出运算符
func overFlowOperator()->Void{
     //Int8的取值范围是 -128 - 127
    
    
    //溢出加
    var num = Int8.max
    //num+=1//溢出报错
    num &+= 1
    print(num)//-128
    
    
    //溢出减
    var num2 = Int8.min
    //num2 -= 1//溢出报错
    num2 &-= 1
    print(num2)//127
    
    
    //溢出乘
    var num3 = Int8.max
    //num3 *= 3//溢出报错
    num3 &*= 2 //相当于 num3 + num3
    print(num3)//-2
}

重载运算符

/// 五、重载运算符
//需要定义成全局的才可以定义重载运算符
struct Point{
    var x:Int
    var y:Int
    init(_ x:Int,_ y:Int) {
        self.x = x
        self.y = y
    }
    
    //重载 + 号运算符
    static func + (p1:Point,p2:Point) -> Point {
        Point(p1.x + p2.x,p1.y + p2.y)
    }
    
    //重载 - 号运算符
    static func - (p1:Point,p2:Point) -> Point {
        Point(p1.x - p2.x,p1.y - p2.y)
    }
    
    
    //重载 += 号运算符
    static func += (p1: inout Point,p2:Point){
        //        p1.x += p2.x
        //        p1.y += p2.y
        p1 = p1 + p2
    }
    
    
    //实现 prefix ++
    static prefix func ++ (p:inout Point)->Point{
        p += Point(1,1)
        return p
    }
    
    //实现 postfix ++
    static postfix func ++ (p:inout Point)->Point{
        let temp = p
        p += Point(1,1)
        return temp
    }
    
    
    //实现==
    static func == (p1:Point,p2:Point)->Bool{
        (p1.x == p2.x && p1.y == p2.y)
    }
}
func overloadOperator() -> Void {
    
    var p1 = Point(1,2)
    let p2 = Point(10,20)
    let p3 = p1 + p2
    let p4 = p2 - p1
    print(p3,p4)//Point(x: 11, y: 22) Point(x: 9, y: 18)
    
    print("--------------")
    
    p1 += p2
    print(p1)//Point(x: 11, y: 22)
    
    let p5 = ++p1
    print(p5)//Point(x: 12, y: 23)
    
    let p6 = p1++
    print(p6)//Point(x: 12, y: 23)
    
    print("--------------")
    
    let p7 = Point(10,20)
    print(p1 == p7)//false
    print(p2 == p7)//true
}

Equatable的用法

/// 六、Equatable的用法
func equatableUse() -> Void {
    
    struct Point2:Equatable{
        var x:Int,y:Int
        init(_ x:Int,_ y:Int) {
            self.x = x
            self.y = y
        }
        
        static func == (p1:Point2,p2:Point2)->Bool{
            (p1.x == p2.x) && (p1.y == p2.y)
        }
    }

    struct Point3:Equatable {
        var x:Int,y:Int
    }

    
    //要想得知2个实例是否等价,一般做法是遵守Equatable 协议,重载== 运算符
    //与此同时,等价于重载了 != 运算符
    let p1 = Point2(1,10)
    let p2 = Point2(2,20)
    print(p1 == p2)//false
    
    //如果不遵从Equatable协议不会自动生成 != 重载
    print(p1 != p2)//true
    
    print("-------------")
    
        
    //Swift为以下类型提供默认的Equatable 实现
    //没有关联类型的枚举
    //只拥有遵守 Equatable 协议关联类型的枚举
    //只拥有遵守 Equatable 协议存储属性的结构体

    let p3 = Point3(x: 1, y: 1)
    let p4 = Point3(x: 2, y: 2)
    print(p3 == p4)//false
    print(p3 != p4)//true
    
     print("-------------")
    
    //引用类型比较存储的地址值是否相等(是否引用着同一个对象),使用恒等运算符=== 、!==

    class Person{
        
    }
    
    
    let per1 = Person()
    var per2 = Person()
    print(per1 === per2)//false
    print(per1 !== per2)//true
    
    per2 = per1
    print(per1 === per2)//true
}

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.