说服Swift的一个函数永远不会返回,由于抛出的异常 [英] Convincing Swift that a function will never return, due to a thrown Exception
问题描述
因为Swift没有抽象方法,我创建一个方法,其默认实现无条件地引发错误。这迫使任何子类重写抽象方法。我的代码看起来像这样:
Because Swift does not have abstract methods, I am creating a method whose default implementation unconditionally raises an error. This forces any subclass to override the abstract method. My code looks like this:
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
语句,编译失败。我需要一些方法来说服编译器这个函数永远不能完成执行,因为它总是会引发一个错误。
The problem: Because the function is expected to return a value, and the above function has no return
statement, compilation fails. I need some way to convince the compiler that this function could never complete execution, because it will always raise an error.
当所有的错误处理看起来都是库级别的时候,如何在Swift中做到这一点,因此超出了编译器的理解?
How could this be done in Swift, when all of the error-handling seems be library-level, and therefore beyond the understanding of the compiler? Is there any kind of language-level feature for (hopefully gracefully) terminating the execution of a program?
推荐答案
Swift的 @noreturn
属性标记
Swift's @noreturn
attribute marks functions and methods as not returning to their caller.
作为最简单的例子,内置函数的签名 abort()
的是:
As probably the simplest example, the signature of the built-in function abort()
's is:
@noreturn func abort()
这为编译器提供了所需的所有信息。例如,下面的代码将编译得很好:
This gives the compiler all the information it needs. For example, the following will compile just fine:
func alwaysFail() -> Int {
abort()
}
alwaysFail()理论上返回一个 Int
,Swift知道执行在 abort()
被调用。
Although alwaysFail()
theoretically returns an Int
, Swift knows that execution can't continue after abort()
is called.
我的原始代码不工作的原因是因为 NSException.raise
是一个pre-Swift方法,因此没有 @noreturn
属性。为了方便解决这个问题,我可以使用 abort()
:
The reason my original code didn't work is because NSException.raise
is a pre-Swift method, and therefore doesn't have the @noreturn
attribute. To easily solve this, I can either use abort()
:
func shouldBeOverridden() -> ReturnType {
println("Subclass has not implemented abstract method `shouldBeOverridden`!")
abort()
}
或者,如果我仍然想使用 NSException
,我可以使用正确的属性
or, if I still want to use NSException
, I can define an extension with the proper attribute
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()
使用扩展
的早期选项实际上只是一个抽象:
As a third option, I can just use a never-called abort()
after an NSException.raise()
to placate the compiler. The earlier option, using an extension
, is really just an abstraction for doing this:
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
}
这篇关于说服Swift的一个函数永远不会返回,由于抛出的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!