# Swift里的值类型与引用类型
-----------------
> 翻译:[老码团队翻译组-Arya](http://weibo.com/littlekok/)
> 校对:[老码团队翻译组-Jame](http://weibo.com/u/5241713117)
本页包含内容:
[TOC=3,4]
### Swift里面的类型分为两种:
* **值类型(Value Types)**:每个实例都保留了一分独有的数据拷贝,一般以结构体 `(struct)`、`枚举(enum)` 或者`元组(tuple)`的形式出现。
* **引用类型(Reference Type)**:每个实例共享同一份数据来源,一般以`类(class)`的形式出现。
在这篇博文里面,我们会介绍两种类型各自的优点,以及应该怎么选择使用。
#### 值类型与引用类型的区别
值类型和引用类型最基本的分别在复制之后的结果。当一个值类型被复制的时候,相当于创造了一个完全独立的实例,这个实例保有属于自己的独有数据,数据不会受到其他实例的数据变化影响:
```swift
// 下面是一个值类型的例子
struct S { var data: Int = -1 }
var a = S()
var b = a // b是a的拷贝
a.data = 42 // 更改a的数据,b的不受影响
println("\(a.data), \(b.data)") // 输出结果 "42, -1"
```
值类型就好像身份证复印件一样,复印出来之后,修改原件上面的内容,复印件上的内容不会变。
另一方面,复制一个引用类型的时候,实际上是默默地创造了一个共享的实例分身,两者是共用一套数据。因此修改其中任何一个实例的数据,也会影响到另外那个。
```swift
// 下面是一个引用类型的例子
class C { var data: Int = -1 }
var x = C()
var y = x // y是x的拷贝
x.data = 42 // 更改x的数据,等于同时修改了y
println("\(x.data), \(y.data)") // 输出结果 "42, 42"
```
#### Mutation(修改)在安全中扮演的角色
值类型较引用类型来说,会让你更容易在大量代码中理清状况。如果你总是得到一个独立的拷贝出来的实例,你就可以放心它不会被你app里面的其他部分代码默默地修改。这在多线程的环境里面是尤为重要的,因为另外一个线程可能会在暗地里修改你的数据。因此可能会造成严重的程序错误,这在调试过程中非常难以排除。
由于差别主要在于修改数据的后果,那么当实例的数据只读,不存在需要更改的情况下,用哪种类型都是没有分别的。
你可能在想,有的时候我可能也需要一个完全不变的类。这样使用`Cocoa NSObject`对象的时候会比较容易,又可以保留值语义的好处。在今天,你可以通过只使用不可变的存储属性,和避开任何可以修改状态的API,用Swift写出一个不可变类`(immutable class)`。实际上,很多基本的Cocoa类,例如`NSURL`,都是设计成不可变类的。然而,Swift语言目前只强制`struct`和`enum`这种值类型的不可变性,对类这种引用类型则没有。(例如还不支持强制将子类的限制为不可变类)
#### 如何选择类型?
所以当我们想要建立一个新的类型的时候,怎么决定用值类型还是引用类型呢?当你使用Cocoa框架的时候,很多API都要通过NSObject的子类使用,所以这时候必须要用到引用类型class。在其他情况下,有下面几个准则:
* **什么时候该用值类型**:
* 要用==运算符来比较实例的数据时
* 你希望那个实例的拷贝能保持独立的状态时
* 数据会被多个线程使用时
* **什么时候该用引用类型(class)**:
* 要用==运算符来比较实例身份的时候
* 你希望有创建一个共享的、可变对象的时候
在Swift里面,数组(Array)、字符串(String)、字典(Dictionary)都属于值类型。它们就像C语言里面简单的int值,是一个个独立的数据个体。你不需要花任何功夫来防范其他代码在暗地里修改它们。更重要的是,你可以在线程之间安全的传递变量,而不需要特地去同步。在Swift高安全性的精神下,这个模式会帮助你用Swift写出更可控的代码。
-----------------
本章节不是老码的原创,老码认真的阅读了苹果的官方博客,且自己的练习总结,如果小伙伴们费了吃奶的劲还是看不懂,请找度娘谷歌,还是看不懂请到老码[官方微博](http://weibo.com/u/5241713117)咆哮。
##### 本文由翻译自Apple Swift Blog :[Value and Reference Types](https://developer.apple.com/swift/blog/?id=10)
- 关于
- 欢迎使用 Swift
- 关于 Swift
- Swift 初见
- Swift 版本历史记录
- Swift 1.0 发布内容
- Swift 教程
- 基础部分
- 基本运算符
- 字符串和字符
- 集合类型
- 控制流
- 函数
- 闭包
- 枚举
- 类和结构体
- 属性
- 方法
- 下标
- 继承
- 构造过程
- 析构过程
- 自动引用计数
- 可选链
- 错误处理
- 类型转换
- 嵌套类型
- 扩展
- 协议
- 泛型
- 访问控制
- 高级运算符
- 语言参考
- 关于语言参考
- 词法结构
- 类型
- 表达式
- 语句
- 声明
- 特性
- 模式
- 泛型参数
- 语法总结
- 苹果官方Blog官方翻译
- Access Control 权限控制的黑与白
- 造个类型不是梦-白话Swift类型创建
- WWDC里面的那个“大炮打气球”
- Swift与C语言指针友好合作
- 引用类型和值类型的恩怨
- 访问控制和Protected
- 可选类型完美解决占位问题