说服 Swift 由于抛出的异常,函数将永远不会返回
Convincing Swift that a function will never return, due to a thrown Exception
因为Swift没有抽象方法,我正在创建一个默认实现无条件引发错误的方法。这会强制任何子类覆盖抽象方法。我的代码如下所示:
class SuperClass {
func shouldBeOverridden() -> ReturnType {
let exception = NSException(
name: "Not implemented!",
reason: "A concrete subclass did not provide its own implementation of shouldBeOverridden()",
userInfo: nil
)
exception.raise()
}
}
问题:因为函数要return一个值,而上面的函数没有return
语句,编译失败。我需要一些让编译器相信这个函数永远无法完成执行的方法,因为它总是会引发错误。
在 Swift 中,当所有错误处理似乎都是库级的,因此超出了编译器的理解范围时,如何做到这一点?是否有任何类型的语言级功能(希望优雅地)终止程序的执行?
听起来您正在做的事情会更好地通过创建一个协议并使 shouldBeOverridden
成为必需的方法,然后让您的 类 遵守该协议。 https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html
Swift 的 @noreturn
属性将函数和方法标记为不返回其调用者。
作为最简单的例子,内置函数 abort()
的签名是:
@noreturn func abort()
这为编译器提供了它需要的所有信息。例如,以下将编译得很好:
func alwaysFail() -> Int {
abort()
}
虽然alwaysFail()
理论上returns一个Int
,Swift知道在调用abort()
后无法继续执行。
我的原始代码不起作用的原因是因为 NSException.raise
是一个 pre-Swift 方法,因此没有 @noreturn
属性。为了轻松解决这个问题,我可以使用 abort()
:
func shouldBeOverridden() -> ReturnType {
println("Subclass has not implemented abstract method `shouldBeOverridden`!")
abort()
}
或者,如果我仍然想使用 NSException
,我可以定义一个具有适当属性的扩展
extension NSException {
@noreturn func noReturnRaise() {
self.raise()
abort() // This will never run, but Swift will complain that the function isn't really @noreturn if I don't call a @noreturn function before execution finishes.
}
}
作为第三种选择,我可以在 NSException.raise()
之后使用从未调用的 abort()
来安抚编译器。较早的选项,使用 extension
,实际上只是执行此操作的抽象:
func shouldBeOverridden() -> ReturnType {
let exception = NSException(
name: "Not implemented!",
reason: "A concrete subclass did not provide its own implementation of shouldBeOverridden()",
userInfo: nil
)
exception.raise()
abort() // never called
}
在 Xcode 8 beta 6 (Swift 3 beta 6) 中,您现在可以使用 Never
return 类型而不是 @noreturn
来表示函数不会 return 给它的调用者:
func crash() -> Never {
fatalError("Oops")
}
创建一个计算的 属性 返回一个名为 abstract
或 overrideMe
或类似的 Never
怎么样,像这样:
var abstract: Never { fatalError("Must be overridden") }
用法示例:
class AbstractTableViewCell: UITableViewCell {
func configure(with model: Any) { abstract }
}
final class ContactTableViewCell: AbstractTableViewCell {
override func configure(with model: Any) {
/* Real implementation here */
}
}
因为Swift没有抽象方法,我正在创建一个默认实现无条件引发错误的方法。这会强制任何子类覆盖抽象方法。我的代码如下所示:
class SuperClass {
func shouldBeOverridden() -> ReturnType {
let exception = NSException(
name: "Not implemented!",
reason: "A concrete subclass did not provide its own implementation of shouldBeOverridden()",
userInfo: nil
)
exception.raise()
}
}
问题:因为函数要return一个值,而上面的函数没有return
语句,编译失败。我需要一些让编译器相信这个函数永远无法完成执行的方法,因为它总是会引发错误。
在 Swift 中,当所有错误处理似乎都是库级的,因此超出了编译器的理解范围时,如何做到这一点?是否有任何类型的语言级功能(希望优雅地)终止程序的执行?
听起来您正在做的事情会更好地通过创建一个协议并使 shouldBeOverridden
成为必需的方法,然后让您的 类 遵守该协议。 https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html
Swift 的 @noreturn
属性将函数和方法标记为不返回其调用者。
作为最简单的例子,内置函数 abort()
的签名是:
@noreturn func abort()
这为编译器提供了它需要的所有信息。例如,以下将编译得很好:
func alwaysFail() -> Int {
abort()
}
虽然alwaysFail()
理论上returns一个Int
,Swift知道在调用abort()
后无法继续执行。
我的原始代码不起作用的原因是因为 NSException.raise
是一个 pre-Swift 方法,因此没有 @noreturn
属性。为了轻松解决这个问题,我可以使用 abort()
:
func shouldBeOverridden() -> ReturnType {
println("Subclass has not implemented abstract method `shouldBeOverridden`!")
abort()
}
或者,如果我仍然想使用 NSException
,我可以定义一个具有适当属性的扩展
extension NSException {
@noreturn func noReturnRaise() {
self.raise()
abort() // This will never run, but Swift will complain that the function isn't really @noreturn if I don't call a @noreturn function before execution finishes.
}
}
作为第三种选择,我可以在 NSException.raise()
之后使用从未调用的 abort()
来安抚编译器。较早的选项,使用 extension
,实际上只是执行此操作的抽象:
func shouldBeOverridden() -> ReturnType {
let exception = NSException(
name: "Not implemented!",
reason: "A concrete subclass did not provide its own implementation of shouldBeOverridden()",
userInfo: nil
)
exception.raise()
abort() // never called
}
在 Xcode 8 beta 6 (Swift 3 beta 6) 中,您现在可以使用 Never
return 类型而不是 @noreturn
来表示函数不会 return 给它的调用者:
func crash() -> Never {
fatalError("Oops")
}
创建一个计算的 属性 返回一个名为 abstract
或 overrideMe
或类似的 Never
怎么样,像这样:
var abstract: Never { fatalError("Must be overridden") }
用法示例:
class AbstractTableViewCell: UITableViewCell {
func configure(with model: Any) { abstract }
}
final class ContactTableViewCell: AbstractTableViewCell {
override func configure(with model: Any) {
/* Real implementation here */
}
}