在Swift中,可以使用非抛出函数来满足抛出函数协议需求,这在某些情况下非常有用。例如,假设我们已经为解析器定义了一个协议,它允许我们以某种方式对字符串进行标记:

protocol TokenParser {
    func parseToken(from string: String) throws -> Token
}

虽然上述协议的某些实现需要抛出,但这并不一定适用于所有符合标准的类型。例如,下面的KeywordParser会抛出错误,而TextParser不会:

struct KeywordParser: TokenParser {
    func parseToken(from string: String) throws -> Token {
        ...
    }
}
struct TextParser: TokenParser {
    // This will satisfy our protocol requirement, even though
    // this implementation doesn't actually throw:
    func parseToken(from string: String) -> Token {
        ...
    }
}

由于协议函数的原始声明被标记为throw,所以当不知道确切的符合类型时,无论底层实现是否真正抛出,我们都需要使用try调用它:

let parsers: [TokenParser] = ...

for parser in parsers {
    // Since all we know about each parser within this iteration
    // is that it conforms to our 'TokenParser' protocol, we'll
    // need to use 'try' when calling its function:
    let token = try parser.parseToken(from: string)
}

然而,当直接处理非抛出类型时,我们现在可以省略try关键字——即使原来的协议要求被标记为抛出:

let parser = TextParser()
let text = parser.parseToken(from: string)

这是一个小特性,但是我们可以使用非抛出函数来实现抛出函数需求,这在符合包含此类函数的协议时,给了我们更大的灵活性。

原文链接