Error 泛型

2019-08-21  本文已影响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
不透明类型 是为了只开放类型里面的部分接口 (也就是协议里面定义的接口) 不暴露类型
上一篇下一篇

猜你喜欢

热点阅读