美文网首页Swift
Swift Day12 错误处理 泛型

Swift Day12 错误处理 泛型

作者: 望穿秋水小作坊 | 来源:发表于2020-12-12 21:24 被阅读0次

    一、错误(异常)

    1. Swift 我们定义异常需要怎么做?
    • Swift 中可以通过 Error 协议自定义运行时的错误信息
    enum SomeError : Error {
        case illegalArg(String)
        case outOfBounds(Int, Int)
        case outOfMemory
    }
    
    2. 函数内部如何抛出错误?函数声明要加上什么?
    • 函数内部通过 throw 抛出自定义 Error
    • 可能会抛出 Error 的函数必须加上 throws 声明
    func divide(_ num1: Int, _ num2: Int) throws -> Int {
        if num2 == 0 {
            throw SomeError.illegalArg("0 不能做为除数")
        }
        return num1 / num2
    }
    
    3. 如何调用一个有错误抛出的函数?
    • 使用 trytry?try! 关键字
    var result1 = try divide(100, 0);
    var result2 = try? divide(100, 0);
    var result3 = try! divide(100, 0);
    
    4. 如何捕捉错误?错误爆出,会影响后续代码的执行吗?
    • 使用 do-catch 捕捉错误
    • 抛出 Error 后,try 下一句直到作用域结束的代码都将停止运行
    func test() {
        print("1")
        do {
            print("2")
            print(try divide(100, 0))
            print("3")
        } catch let SomeError.illegalArg(msg) {
            print("参数异常:", msg)
        } catch let SomeError.outOfBounds(size, index) {
            print("下标越界:", size, index)
        } catch SomeError.outOfMemory {
            print("内存溢出")
        } catch {
            print("未知错误")
        }
        print("4")
    }
    
    • 上述代码将打印 1 2 参数异常:0不能作为除数 4
    5. try?、try!处理错误的时候和 try 有什么不同?
    • 可以使用 try?、try! 调用可能会抛出 Error 的函数,这样就不需要去处理 Error
    func test2() {
        print("1")
        var result1 = try? divide(20, 10)   // Optional(2), Int?
        var result2 = try? divide(20, 0)    // nil, Int?
        var result3 = try! divide(20, 10)   // 2, Int
    }
    
    6. defer 关键字有什么用?举一个实际例子说明?
    • defer 语句:用来定义以任何方式(抛错误、return 等)离开代码块必须要执行的代码
    • defer 语句将延迟至当前作用域结束之前执行
    defer

    二、泛型(Generics)

    1. 泛型(Generics)这个技术出现的目的是什么?
    • 泛型可以将类型参数化,提高代码复用率,减少代码量
    泛型
    2. 思考下面代码,红框内的 <T> 可以省略掉吗?
    示例
    • 不能省略掉,省略之后就是普通函数了,编译器会认为 T 是一个自定义类型,如果找不到 T 的定义,就会编译报错
    3. 思考为什么下列代码中,不需要像声明函数一样,加上 T 的类型说明?
    示例
    • 因为调用函数的时候当 i1 传入的时候,编译器就可以确认 T 的类型,所以无需额外说明
    • 总结:就是要有办法让编译器在调用之时能确定 T 的类型
    4. 我们声明 func 中泛型的时候一般用什么字母表示,我们声明 class 中的泛型的时候一般用什么字母表示,分别代表什么?
    • func 中泛型的时候一般用 T,表示 Type
    • class 中泛型的时候一般用 E,表示 Element
    class 中使用泛型
    5. 泛型在 Class、Enum、Struct 中(了解)
    示例
    6.思考泛型的本质是什么呢?或者说实现原理?
    • 在 C++中,编译器会根据代码需要,给泛型生成多个函数
    C++的做法
    • 当需要 Int 类型的泛型函数时,会生成注释 1 的函数
    • 当需要 Double 类型的泛型函数时,会生成注释 2 的函数
    • 那么在 Swift 中采取的做法是否和 C++一样呢
    Int 的 swapValues 函数调用地址 Double 的swapValues 函数调用地址
    • 对比发现,两次调用的函数地址都一样,说明 Swift 采取的做法和 C++是不同的。
    Swift 的做法
    • 可以发现,Swift 将参数的 type metadata 当成函数传入了 callq
    • Swift 是将 type metadata 作为函数的依据,来区别对待传入的泛型
    7. 如果想在协议中使用泛型怎么做?
    • 我们之前学过的泛型都是用在 类、结构体、枚举、函数
    • 在协议中想要使用泛型,需要使用 关联类型(associated type) 技术
    关联类型
    8. 如果想对泛型进行约束要怎么做?(了解即可)
    泛型约束

    相关文章

      网友评论

        本文标题:Swift Day12 错误处理 泛型

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