Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么是';抛出';Swift中的类型不安全?_Swift_Try Catch_Throw - Fatal编程技术网

为什么是';抛出';Swift中的类型不安全?

为什么是';抛出';Swift中的类型不安全?,swift,try-catch,throw,Swift,Try Catch,Throw,对我来说,Swift中最大的误解是抛出关键字。考虑下面的代码: func myUsefulFunction() throws 我们无法真正理解它会带来什么样的错误。我们唯一知道的是,它可能会抛出一些错误。理解错误的唯一方法是查看文档或在运行时检查错误 但这不是违背了斯威夫特的天性吗?Swift具有强大的泛型和类型系统,可以使代码具有表达能力,但它感觉好像抛出的正好相反,因为您无法从查看函数签名中获得任何有关错误的信息 为什么会这样?还是我错过了一些重要的东西而误解了这个概念?这个选择是经过深思

对我来说,Swift中最大的误解是
抛出
关键字。考虑下面的代码:

func myUsefulFunction() throws
我们无法真正理解它会带来什么样的错误。我们唯一知道的是,它可能会抛出一些错误。理解错误的唯一方法是查看文档或在运行时检查错误

但这不是违背了斯威夫特的天性吗?Swift具有强大的泛型和类型系统,可以使代码具有表达能力,但它感觉好像
抛出的
正好相反,因为您无法从查看函数签名中获得任何有关错误的信息


为什么会这样?还是我错过了一些重要的东西而误解了这个概念?

这个选择是经过深思熟虑的设计决定

他们不希望在Objto-C、C++和Cyl中不需要声明异常抛出的情况,因为这使得调用方必须假定所有函数都抛出异常,并且包含样板来处理可能不发生的异常,或者忽略异常的可能性。这两种方法都不理想,第二种方法使异常无法使用,除非您想终止程序,因为您不能保证调用堆栈中的每个函数在堆栈展开时都正确释放了资源

另一个极端是您提倡的想法,即可以声明抛出的每种类型的异常。不幸的是,人们似乎反对这样做的结果,即您有大量的catch块,因此您可以处理每种类型的异常。因此,例如,在Java中,他们会抛出
异常
将情况降低到与Swift中相同的程度,或者更糟,他们使用未经检查的异常,这样您就可以完全忽略问题。GSON库就是后一种方法的一个例子

我们选择使用未检查的异常来指示解析失败。这主要是因为客户机通常无法从错误的输入中恢复,因此强制客户机捕获已检查的异常会导致catch()块中的代码不完整

这是一个极其糟糕的决定。“您好,您不能被信任自行处理错误,因此您的应用程序应该崩溃”

就我个人而言,我认为斯威夫特的平衡是正确的。您必须处理错误,但不必为此编写大量的catch语句。如果他们再进一步,人们就会找到颠覆机制的方法

设计决策的全部理由如下:

编辑

似乎有些人对我说的一些话有意见。这里有一个解释

程序可能抛出异常的原因有两大类

  • 程序外部环境中的意外情况,如文件IO错误或数据格式错误。这些是应用程序通常可以处理的错误,例如通过向用户报告错误并允许用户选择不同的操作过程
  • 编程错误,如空指针或数组绑定错误。解决这些问题的正确方法是程序员进行代码更改
第二类错误通常不应被捕获,因为它们表明对环境的错误假设,这可能意味着程序的数据已损坏。没有办法安全继续,所以你必须中止

第一类错误通常可以恢复,但为了安全恢复,每个堆栈帧都必须正确展开,这意味着与每个堆栈帧对应的函数必须知道它调用的函数可能引发异常,并采取步骤确保在引发异常(例如,使用finally块或等效块)时,所有内容都得到一致的清理。如果编译器不支持告诉程序员他们忘记计划异常,那么程序员就不会总是计划异常,并且会编写泄漏资源或使数据处于不一致状态的代码

gson态度如此令人震惊的原因是,他们说您无法从解析错误中恢复(实际上,更糟糕的是,他们告诉您,您缺乏从解析错误中恢复的技能)。这是一个荒谬的断言,人们总是试图解析无效的JSON文件。如果有人错误地选择了XML文件,我的程序就会崩溃,这是一件好事吗?不,不是。它应该报告问题并要求他们选择其他文件


顺便说一下,gson只是一个例子,说明了为什么对可以恢复的错误使用未检查的异常是不好的。如果我确实想从选择XML文件的人那里恢复,我需要捕获Java运行时异常,但是哪些异常呢?好吧,我可以看看Gson的文档来找出答案,假设它们是正确的和最新的。如果它们带有检查过的异常,API会告诉我将出现哪些异常,编译器会告诉我是否没有处理这些异常。

我是Swift中类型错误的早期支持者。这就是为什么Swift团队让我相信我错了

强类型错误在某些方面是脆弱的,可能会导致API进化不良。如果API承诺只抛出3个错误中的一个,那么在以后的版本中出现第四个错误情况时,我有一个选择:我将它以某种方式埋在现有的3个错误中,或者我强制每个调用方重写错误处理代码来处理它。因为它不在最初的3中,所以它可能不是一种非常常见的情况,这给API施加了很大的压力,使其不能扩展错误列表,特别是当框架在很长一段时间内被广泛使用时(想想:Foundation)

当然,对于开放枚举,我们可以避免这种情况,但开放枚举无法实现强类型错误的任何目标。这基本上是一个非类型错误
} catch {
    logError(error)
    return
}
func something() throws MyError { }