@ -20,29 +20,20 @@
< a name = "comparing_classes_and_structures" ></ a >
###类和结构体对比
Swift 中类和结构体有很多共同点。共同处在于:
<<<<<< < HEAD
* 定义属性用于储存值
* 定义方法用于提供功能
* 定义附属脚本用于访问值
* 定义构造器用于生成初始化值
* 通过扩展以增加默认实现的功能
* 符合协议以对某类提供标准功能
= ======
* 定义属性用于储存值
* 定义方法用于提供功能
* 定义下标脚本用于访问值
* 定义构造器用于生成初始化值
* 通过扩展以增加默认实现的功能
* 符合协议以对某类提供标准功能
> >>>>>> a516af6a531a104ec88da0d236ecf389a5ec72af
更多信息请参见 [属性 ](10_Properties.html ), [方法 ](11_Methods.html ), [下标脚本 ](12_Subscripts.html ), [初始过程 ](14_Initialization.html ), [扩展 ](20_Extensions.html ),和[协议 ](21_Protocols.html )。
与结构体相比,类还有如下的附加功能:
* 继承允许一个类继承另一个类的特征
* 类型转换允许在运行时检查和解释一个类实例的类型
* 解构器允许一个类实例释放任何其所被分配的资源
@ -54,6 +45,7 @@ Swift 中类和结构体有很多共同点。共同处在于:
结构体总是通过被复制的方式在代码中传递,因此请不要使用引用计数。
### 定义
类和结构体有着类似的定义方式。我们通过关键字`class` 和`struct` 来分别表示类和结构体,并在一对大括号中定义它们的具体内容:
```swift
@ -88,6 +80,7 @@ class VideoMode {
在上面的示例中我们还定义了一个名为`VideoMode` 的类,用来描述一个视频显示器的特定模式。这个类包含了四个储存属性变量。第一个是`分辨率` ,它被初始化为一个新的`Resolution` 结构体的实例,具有`Resolution` 的属性类型。新`VideoMode` 实例同时还会初始化其它三个属性,它们分别是,初始值为`false` (意为“non-interlaced video”)的`inteflaced` ,回放帧率初始值为`0.0` 的`frameRate` 和值为可选`String` 的`name` 。`name` 属性会被自动赋予一个默认值`nil` ,意为“没有`name` 值”,因它是一个可选类型。
### 类和结构体实例
`Resolution` 结构体和`VideoMode` 类的定义仅描述了什么是`Resolution` 和`VideoMode` 。它们并没有描述一个特定的分辨率( resolution) 或者视频模式( video mode) 。为了描述一个特定的分辨率或者视频模式, 我们需要生成一个它们的实例。
生成结构体和类实例的语法非常相似:
@ -99,8 +92,8 @@ let someVideoMode = VideoMode()
结构体和类都使用构造器语法来生成新的实例。构造器语法的最简单形式是在结构体或者类的类型名称后跟随一个空括弧,如`Resolution()` 或`VideoMode()` 。通过这种方式所创建的类或者结构体实例,其属均会被初始化为默认值。[构造过程 ](14_Initialization.html )章节会对类和结构体的初始化进行更详细的讨论。
### 属性访问
通过使用*点语法*( *dot syntax*) ,你可以访问实例中所含有的属性。其语法规则是,实例名后面紧跟属性名,两者通过点号(.)连接:
```swift
@ -199,6 +192,7 @@ if rememberDirection == .West {
< a name = "classes_are_reference_types" ></ a >
## 类是引用类型
与值类型不同,引用类型在被赋予到一个变量,常量或者被传递到一个函数时,操作的并不是其拷贝。因此,引用的是已存在的实例本身而不是其拷贝。
请看下面这个示例,其使用了之前定义的`VideoMode` 类:
@ -257,10 +251,12 @@ if tenEighty === alsoTenTighty {
当你在定义你的自定义类和结构体的时候,你有义务来决定判定两个实例“相等”的标准。在章节[运算符函数(Operator Functions) ](23_Advanced_Operators.html#operator_functions )中将会详细介绍实现自定义“等于”和“不等于”运算符的流程。
### 指针
如果你有 C, C++ 或者 Objective-C 语言的经验,那么你也许会知道这些语言使用指针来引用内存中的地址。一个 Swift 常量或者变量引用一个引用类型的实例与 C 语言中的指针类似,不同的是并不直接指向内存中的某个地址,而且也不要求你使用星号(*) 来表明你在创建一个引用。Swift 中这些引用与其它的常量或变量的定义方式相同。
< a name = "choosing_between_classes_and_structures" ></ a >
## 类和结构体的选择
在你的代码中,你可以使用类和结构体来定义你的自定义数据类型。
然而,结构体实例总是通过值传递,类实例总是通过引用传递。这意味两者适用不同的任务。当你的在考虑一个工程项目的数据构造和功能的时候,你需要决定每个数据构造是定义成类还是结构体。
@ -282,6 +278,7 @@ if tenEighty === alsoTenTighty {
< a name = "assignment_and_copy_behavior_for_collection_types" ></ a >
## 集合( Collection) 类型的赋值和拷贝行为
Swift 中`数组( Array) ` 和`字典( Dictionary) ` 类型均以结构体的形式实现。然而当数组被赋予一个常量或变量,或被传递给一个函数或方法时,其拷贝行为与字典和其它结构体有些许不同。
以下对`数组` 和`结构体` 的行为描述与对`NSArray` 和`NSDictionary` 的行为描述在本质上不同,后者是以类的形式实现,前者是以结构体的形式实现。`NSArray` 和`NSDictionary` 实例总是以对已有实例引用,而不是拷贝的方式被赋值和传递。
@ -291,6 +288,7 @@ Swift 中`数组( Array) `和`字典( Dictionary) `类型均以结构体的
在你的代码中,拷贝好像是确实是在有拷贝行为的地方产生过。然而,在 Swift 的后台中,只有确有必要,`实际( actual) ` 拷贝才会被执行。Swift 管理所有的值拷贝以确保性能最优化的性能,所以你也没有必要去避免赋值以保证最优性能。(实际赋值由系统管理优化)
### 字典类型的赋值和拷贝行为
无论何时将一个`字典` 实例赋给一个常量或变量,或者传递给一个函数或方法,这个字典会即会在赋值或调用发生时被拷贝。在章节[结构体和枚举是值类型 ](#structures_and_enumerations_are_value_types )中将会对此过程进行详细介绍。
如果`字典` 实例中所储存的键( keys) 和/或值( values) 是值类型( 结构体或枚举) , 当赋值或调用发生时, 它们都会被拷贝。相反, 如果键( keys) 和/或值( values) 是引用类型, 被拷贝的将会是引用, 而不是被它们引用的类实例或函数。`字典` 的键和值的拷贝行为与结构体所储存的属性的拷贝行为相同。
@ -368,6 +366,7 @@ println(c[0])
```
### 确保数组的唯一性
在操作一个数组,或将其传递给函数以及方法调用之前是很有必要先确定这个数组是有一个唯一拷贝的。通过在数组变量上调用`unshare` 方法来确定数组引用的唯一性。(当数组赋给常量时,不能调用`unshare` 方法)
如果一个数组被多个变量引用,在其中的一个变量上调用`unshare` 方法,则会拷贝此数组,此时这个变量将会有属于它自己的独立数组拷贝。当数组仅被一个变量引用时,则不会有拷贝发生。