Swift架构 - Scope and Lifetime

在 Swift 程序中,事物有一个作用域。这是指他们被其他事物看到的能力。事物嵌套在其他事物中,形成事物的嵌套层次结构。规则是,事物可以在自己的层次上看到事物,也可以在包含它们的更高层次上看到事物。级别如下:

  • 模块是一个作用域
  • 文件是一个作用域
  • 花括号是一个作用域

当声明某项内容时,它是在该层次结构中的某个级别上声明的。它在等级体系中的位置-它的作用域-决定了它是否可以被其他东西看到。

再看一下例 1-1。Manny的声明里面有一个name变量声明和一个sayName函数声明;在sayName的花括号内的代码可以看到那些花括号外的东西,在更高的包含级别,因此可以看到name变量。类似地,changeOne函数体中的代码可以看到在文件顶层声明的one变量;实际上,该文件中的所有内容都可以看到在文件顶层声明的一个变量。

因此,作用域是共享信息的一种非常重要的方式。在Manny内部声明的两个不同的函数都可以看到在Manny的顶层声明的名字。Jack内部的代码和Moe内部的代码都可以看到在文件顶层声明的代码。

事物也有生命周期,这实际上等同于它们的作用域。物体的寿命和它周围的作用域的寿命一样长。在示例 1-1 中,变量one的寿命与文件的寿命一样长——也就是说,只要程序运行。它是全局性和持续性的。但是Manny顶层声明的变量名只有在Manny实例存在的情况下才存在(我稍后会讨论这意味着什么)。

在更深层次上声明的对象的寿命甚至更短。考虑以下代码:

1
2
3
4
5
6
7
func silly() {
if true {
class Cat {}
var one = 1
one = one + 1
}
}

这段代码很傻,但它是合法的:记住,我说过变量声明、函数声明和对象类型声明可以出现在任何结构花括号中。在这段代码中,类Cat和变量one甚至在有人调用这个愚蠢的函数之前都不会存在,即使这样,它们也只会在代码执行路径通过if结构的短暂瞬间存在。假设调用了silly函数;执行路径随后进入if构造。在这里,Cat被声明并且存在;然后one被声明而存在;然后执行可执行行 one = one + 1;然后,作用域结束了——Catone都消失在一股烟雾中。在它们短暂的生命中,项目的其他部分完全看不到Catone。(你知道为什么吗?)