说服Swift的一个函数永远不会返回,由于抛出的异常 [英] Convincing Swift that a function will never return, due to a thrown Exception

查看:177
本文介绍了说服Swift的一个函数永远不会返回,由于抛出的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆