JHHK

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

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

目录

comparable协议的使用

/// 一、comparable协议的使用
struct Student : Comparable {
    /**
     score大的比较大,若score相等,age小的比较大
     要想比较2个实例的大小,一般做法是:
     遵守 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)
    }
}
func compareableUse(){
    let stu1 = Student(score: 100, age: 20)
    let stu2 = Student(score: 98, age: 18)
    let 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
}

自定义运算符使用

/// 二、自定义运算符使用
/**
 可以自定义新的运算符:在全局作用域使用operator进行声明
 */
prefix operator +++
postfix  operator +++
infix operator +- : PlusMinusPrecedence
precedencegroup PlusMinusPrecedence{
    associativity:left  //left right none  none只允许两个变量做运算 否则会报错
    higherThan:AdditionPrecedence
    lowerThan:MultiplicationPrecedence
    assignment:true //true代表在可选链操作中拥有跟赋值运算符一样的优先级 person?.age = 10   person?.age +- Point(1,1) 及person解包失败是 后边就不再进行
}

struct CustomPoint {
    var x:Int
    var y:Int
    init(x:Int,y:Int){
        self.x = x
        self.y = y
    }
    
    static prefix func +++ (p1:inout CustomPoint)->CustomPoint{
        p1.x+=2
        p1.y+=2
        
        return p1
    }
    
    static postfix func +++ (p1:inout CustomPoint)->CustomPoint{
        let temp = p1
        p1.x+=2
        p1.y+=2
        return temp
    }
    
    
    static func +- (p1:CustomPoint,p2:CustomPoint)->CustomPoint{
        CustomPoint(x:p1.x + p2.x , y:p1.y - p2.y)
    }
}
func customOperatorUse() -> Void {
    var cp = CustomPoint(x: 1, y: 1)
    print(+++cp)
    print(cp)
    print(cp+++)
    print(cp)
    
    let cp1 = CustomPoint(x: 10, y: 10)
    let cp2 = CustomPoint(x: 20, y: 20)
    print(cp1 +- cp2)
}

extension的使用

/// 三、extension的使用
/**
 Swift中的扩展,有点类似于OC中的分类(Category)
 扩展可以为枚举、结构体、类、协议添加新功能
 可以添加方法、计算属性、下标、(便捷)初始化器、嵌套类型、协议等等
 扩展不能办到的事情
    不能覆盖原有的功能
    不能添加存储属性,不能向已有的属性添加属性观察器
    不能添加父类
    不能添加指定初始化器,不能添加反初始化器
    ...
 */

//1、扩展Double类型
extension Double {
    var km: Double { self * 1_000.0 }
    var m:  Double { self }
    var dm: Double { self / 10.0 }
    var cm: Double { self / 100.0 }
    var mm: Double { self / 1_000.0 }
}
func extensionUse1 () {
    let d = 20.0
    print(d.km)//20000.0
}


//2、扩展Int类型
extension Int {
    func repetitions(task: () -> Void) {
        for _ in 0..<self {
            task()
        }
    }
    
    mutating func square() -> Int {
        self = self * self
        return self
    }
    
    enum Kind { case negative, zero, positive }
    var kind: Kind {
        switch self {
        case 0:
            return .zero
        case let x where x > 0:
            return .positive
        default:
            return .negative
        }
    }
    
    subscript(digitIndex: Int) -> Int {
        var decimalBase = 1
        for _ in 0..<digitIndex {
            decimalBase *= 10
        }
        return (self / decimalBase) % 10
    }
}
func extensionUse2 () {
    let i = 2
    i.repetitions {
        print("i = ",i)//
    }
    print(i.kind)//positive
}


//3、扩展Array类型
extension Array {
    subscript(nullable idx: Int) -> Element? {
        if (startIndex..<endIndex).contains(idx) {
            return self[idx]
        }
        return nil
    }
}
func extensionUse3() -> Void {
    let arr = [1,2,3]
    print(arr[0])//1
    
    if let num = arr[nullable:0] {
        print(num)//1
    }else{
        print("越界")
    }
    
    if let num = arr[nullable:0-1] {
        print(num)
    }else{
        print("越界")//越界
    }
}


//4、泛型,扩展中依然可以使用原类型中的泛型类型
class Stack<E> {
    var elements = [E]()
    
    func push(_ element: E) {
        elements.append(element)
    }
    
    func pop() -> E {
        elements.removeLast()
    }
    
    func size() -> Int {
        elements.count
    }
}
extension Stack {
    // 扩展中依然可以使用原类型中的泛型类型
    func top() -> E { elements.last! }
}
// 符合条件才扩展
extension Stack : Equatable where E : Equatable {
    static func == (left: Stack, right: Stack) -> Bool {
        left.elements == right.elements
    }
}
func extensionUse4(){
    let sta1:Stack      = Stack<Int>()
    let sta2:Stack<Int> = Stack<Int>()
    let sta3:Stack<Int> = sta1
    sta1.push(8)
    print(sta1.top()+2)//10
    print(sta1 == sta2)//false
    print(sta1 == sta3)//true
}



//5、通过扩展添加自定义初始化器,能做到保留编译器生成的默认初始化器
/**
 如果希望自定义初始化器的同时,编译器也能够生成默认初始化器
 可以在扩展中编写自定义初始化器
 required初始化器也不能写在扩展中
 */
struct LCPoint {
    var x:Int = 0
    var y:Int = 0
}
extension LCPoint {
    //通过扩展添加了自定义初始化器,但编译器生成初始化器仍然可用
    init(point:LCPoint) {
        self.x = point.x
        self.y = point.y
    }
    
    //required初始化器也不能写在扩展中
    //'required' initializer in non-class type 'LCPoint'
    //required init(p:(Int,Int)){
    init(_ p:(Int,Int)){
        self.x = p.0
        self.y = p.1
    }
}
extension LCPoint : Equatable{
    static func ==(lv:LCPoint,rv:LCPoint) -> Bool {
        (lv.x,lv.y) == (rv.x,rv.y)
    }
}
func extensionUse5() -> Void {
    let point1 = LCPoint(x: 10, y: 20)
    let point2 = LCPoint(point: point1)
    let point3 = LCPoint((10,20))
    print(point1,point2,point3)// LCPoint(x: 10, y: 20) LCPoint(x: 10, y: 20) LCPoint(x: 10, y: 20)
    print(point1 == point2)// true
    print(point1 == point3)// true
}



//6、扩展协议
struct LCTest {
    var x:Int = 0
    var y:Int = 0
    func test1() -> Void {
        print("func test1")
    }
    func test2() -> Void {
        print("func test2")
    }
    func test3() -> Void {
        print("func test3")
    }

}
protocol LCTestProtocol {
    func test1() -> Void
    func test2() -> Void
}

/**
 如果一个类型已经实现了协议的所有要求,但是还没有声明它遵守了这个协议
 可以通过扩展来让它遵守这个协议
 */
extension LCTest : LCTestProtocol{}

/**
 扩展可以给协议提供默认实现,也间接实现『可选协议』的效果
 扩展可以给协议扩充『协议中从未声明过的方法
 */
extension LCTestProtocol {
    //在协议的扩展中添加的方法必须实现,作为默认实现
    //这样遵从这个协议的类,就可以不实现这个方法
    func test3() -> Void {
        print("test3")
    }
}

extension BinaryInteger {
    //提供默认实现
    func isOdd() -> Bool { self % 2 != 0 }
}


func extensionUse6() -> Void {
    
    //1、查看某个类是否遵守了某个协议
    do{
        print("--------1--------")
        let test = LCTest()
        print(test is LCTestProtocol)//true
    }

    //2、提供默认实现
    do{
        print("---------2----------")
        LCTest().test3()    //test3
        print( 2.isOdd())   //false
    }
}

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.