美文网首页
Error 泛型

Error 泛型

作者: 纳兰沫 | 来源:发表于2019-08-21 17:15 被阅读0次

    Error 异常处理 错误处理

    错误类型

    1.语法错误(编译报错)
    2.逻辑错误
    3.运行时错误 (可能会导致闪退 一般也叫做异常)
    

    自定义错误

    可以通过Error协议自定义运行时的错误信息
    enum SomeError: Error {
        case illegalArg(String)
        case outOfBounds(Int, Int)
        case outOfMemory
    }
    
    函数内部通过throw抛出自定义Error 可能会抛出Error的函数必须加上throws声明
    struct MyError: Error {
        var msg: String
    }
    
    func divide(_ num1: Int, _ num2: Int) throws -> Int {
        
        if num2 == 0 {
            throw MyError(msg: "0不能作为除数")
        }
        
        return num1 / num2
    }
    
    需要使用try调用可能会抛出Error的函数
    var result = try divide(2, 0)
    print(result)
    
    错误提示.png

    如何处理错误

    do-catch

    一旦 try 抛出异常 它所在作用域范围内的后面的所有代码都不会执行

    func test() {
        print("1")
        do {
            print("2")
            print(try divide(20, 0))
            print("3")
        }catch let SomeError.illegalArg(msg){
            print("参数异常:", msg)
        }catch let SomeError.outOfBounds(size, index){
            print("下标越界:", "size = \(size)", "index = \(index)")
        }catch SomeError.outOfMemory{
            print("内存溢出")
        }catch {
            print("其他错误")
        }
        print("4")
    }
    
    test()
    
    1
    2
    参数异常: 0不能作为除数
    4
    
    不捕捉Error 在当前函数增加throws声明 Error将自动抛给上层函数
    - 如果最顶层函数(main 函数) 依然没有捕捉Error 那么程序将终止
    
    func test() throws{
        print(try divide(20, 0))
    }
    
    try test()
    
    func test() throws{
        print("1")
        do {
            print("2")
            print(try divide(20, 0))
            print("3")
        }catch let error as SomeError{
            print(error)
        }
        print("4")
    }
    
    try test()
    
    1
    2
    illegalArg("0不能作为除数")
    4
    

    异常一层一层抛出

    func test0 throws {
        try test1()
    }
    
    func test1 throws {
        try test2()
    }
    
    func test2 throws {
        do{
            print(try divide(288, 81))
        }catch is SomeError {
            priht("This is SomeError")
        }
    }
        
    try test0()
    

    try? try!

    可以使用try? try! 调用可能会抛出Error的函数 这样就不用去处理Error
    
    func test() {
        print("1")
        var result1 = try? divide(20, 10)
        var result2 = try? divide(20, 0)
        var result3 = try! divide(20, 10)
        print("2")
    }
    
    test()
    
    a b 是等价
    var a = try? divide(20, 0)
    
    var b: Int?
    do {
        b = try divide(20, 0)
    }catch{
        b = nil
    }
    
    

    rethrows

    rethrows 函数本身不会抛出错误 但是调用闭包函数抛出错误 那么他会将错误往上抛
    

    rethrows 跟 throws 一样抛出异常 只不过 rethrows是由于函数参数是闭包函数导致的异常

    func exec(_ fn: (Int, Int) throws -> Int, _ num1: Int, _ num2: Int) rethrows {
        print(try fn(num1,num2))
    }
    
    try exec(divide, 29, 0)
    

    defer

    用来定义以任何方式(抛错误 return等) 离开代码前必须要执行的代码
    

    defer语句将延迟至当前作用域结束之前执行

    
    func open(_ filename: String) -> Int {
        print("open")
        return 0
    }
    
    func close(_ file: Int) {
        print("close")
    }
    
    
    func processFile(_ filename: String) throws {
        let file = open(filename)
        defer {
            close(file)
        }
        try divide(20, 0)
        
    }
    
    try processFile("test.text")
    

    defer语句的执行顺序与定义顺序相反

    泛型 Generics

    泛型可以将类型参数化 提供代码复用率 减少代码量
    

    T 代表一种不确定的类型

    var n1 = 10
    var n2 = 20
    
    func swapValues<T>(_ a: inout T , _ b: inout T) {
        
       return (a,b) = (b,a)
    }
    
    swap(&n1, &n2)
    
    print(n1,n2)
    

    函数类型 必须明确是什么类型

    var fn: (inout Int, inout Int) -> () = swapValues
    
    泛型类型
    class Stack<E> {
        var elements = [E]()
        func push(_ element: E){
            return elements.append(element)
        }
        func pop() -> E {
            return elements.removeLast()
        }
        func top() -> E {
            return elements.last!
        }
        func size() -> Int {
            return elements.count
        }
    }
    
    var stack = Stack<Int>()
    stack.push(<#T##element: Int##Int#>)
    
    class SubStack<E>: Stack<E> {
        
    }
    
    enum Score<T> {
        case point(T)
        case grade(String)
    }
    
    let score = Score<Int>.grade("A")
    
    关联类型
    1.关联类型的作用  给协议中用到的类型定义一个占位名称
    2.协议中拥有多个关联类型
    
    protocol Stackable {
        associatedtype Element //关联类型
        mutating func push(_ element: Element)
        mutating func pop() -> Element
        func top() -> Element
        func size() -> Int
    }
    
    
    class StringSatck: Stackable {
        //给关联类型设定真实类型
        typealias Element = String
        func push(_ element: Element){
            return elements.append(element)
        }
        func pop() -> Element{
            return elements.removeLast()
        }
        func top() -> Element {
            return elements.last!
        }
        func size() -> Int {
            return elements.count
        }
    }
    
    类型约束
    A2CAAC5E-23BD-4087-823D-3E71156FBCEE.png
    协议类型的注意点
    F305714F-FF8A-41D9-A4E8-7F8CF6B9201D.png
    如果协议中有associatedtype  会报错
    
    D8138A36-3309-4454-AB3B-7C7FAF4031F9.png
    83EF3C18-E8C5-4D50-9F1F-1575303C1BBB.png
    BB53C5DD-A45E-4230-8006-454839C403A9.png
    不透明类型 是为了只开放类型里面的部分接口 (也就是协议里面定义的接口) 不暴露类型

    相关文章

      网友评论

          本文标题:Error 泛型

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