因为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
语句,编译失败。我需要一些方法来说服编译器这个函数永远无法完成执行,因为它总会引发错误。
如果所有的错误处理看起来都是库级的,那么在Swift中怎么做呢?因此超出了对编译器的理解?是否有任何语言级功能(希望优雅地)终止程序的执行?
答案 0 :(得分:24)
Swift的@noreturn
属性将函数和方法标记为不返回其调用者。
可能是最简单的例子,内置函数abort()
的签名是:
@noreturn func abort()
这为编译器提供了所需的所有信息。例如,以下内容编译得很好:
func alwaysFail() -> Int {
abort()
}
虽然alwaysFail()
理论上返回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.
}
}
作为第三种选择,我可以在abort()
之后使用一个永不调用的NSException.raise()
来安抚编译器。使用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
}
答案 1 :(得分:9)
在Xcode 8 beta 6(Swift 3 beta 6)中,您现在可以使用Never
返回类型而不是@noreturn
来指示函数不会返回其调用者:
func crash() -> Never {
fatalError("Oops")
}
答案 2 :(得分:2)
通过创建协议并使shouldBeOverridden
成为必需的方法,然后使您的类符合该协议,听起来您正在做的事情会更好。 https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html
答案 3 :(得分:0)
如何创建一个返回名为from ast import literal_eval
mystr = """{
"key A":[
["some val", "value a1"],
["some val", "value a2"],
["some val", "value an"]
], "key B":[
["some val", "value b1"],
["some val", "value b2"],
], "key X":[
["some val", "value x1"],
["some val", "value x2"],
]
}"""
res = {k: list(list(zip(*v))[1]) for k, v in literal_eval(mystr).items()}
# {'key A': ['value a1', 'value a2', 'value an'],
# 'key B': ['value b1', 'value b2'],
# 'key X': ['value x1', 'value x2']}
或Never
或类似abstract
的{{1}}的计算属性,如下所示:
overrideMe
使用示例:
var abstract: Never { fatalError("Must be overridden") }