Swift 中的值类型与引用类型(Value and Refer

2017-05-21  本文已影响18人  西风那个吹呀吹

Swift 类型分为两种:值类型与引用类型。
值类型:每个实例拥有独一无二的数据拷贝,例如基础数据类型(Int、Float、Double等)、String、集合类型(Dictionary、Set、Array)、元组、枚举、结构体等。
引用类型:每个实例共享唯一一份数据拷贝,一般以类(Class)形式出现。

区别

值类型与引用类型最基本的区别就是拷贝之后的结果,值类型被拷贝的时候,相当于建立一个新的独立的实例,这个实例拥有自己的独有的数据且不受其他实例的数据变化影响。也可以说拷贝在赋值、初始化、传递参数等过程中的数据并为数据创建一个独立的实例。

struct Person{
    var name: String?
    init(name:String?) {
        self.name = name
    }
}

var p1 = Person.init(name: "hehe")
var p2 = p1     //p2是p1的拷贝
p2.name = "haha" //修改p2的数据,p1并不被受影响
print(p1.name!,p2.name!)
//打印:hehe haha

拷贝一个引用类型的时候,本质上是创建一个共享的实例的副本,两者共用一套数据。在拷贝后,两个实例指向了同一份数据,所以修改其一的数据,另一个实例随之改变。

class Person{
    var name: String?
    init(name:String?) {
        self.name = name
    }
}

var p1 = Person.init(name: "hehe")
var p2 = p1     //p2是p1的拷贝
p2.name = "haha" //修改p2的数据,p1的数据随之改变,p1/p2共用一套数据
print(p1.name!,p2.name!)
//打印:haha haha

可变在安全性中的角色

使用值类型可以不用担心在某个地方对数据的修改而影响到其他地方的数据。在多线程环境中非常有用,因为不同的线程有可能会在不知情的情况下改变数据。发生这种Bug后,调试就非常困难。

因为值类型和引用类型的区别就在于当你修改类型实例的数据时,它们对原始类型数据的处理方式不同。但是有一种情况,值类型和引用类型的处理方式却又相似,那就是当类型实例的数据为只读的时候。在不存在修改的情况下,值类型和引用类型就没什么区别了。

在Swift中可以通过定义不可改变的存储属性来创建一个不可变的类,避免暴露出的API被修改。许多普通的Cocoa框架里的类,如NSURL,都被设计成不可变的类。

类型选择

创建一个新类型的时候,如何选择值类型还是引用类型呢?在使用Cocoa框架时,很多API都是NSObject的子类,那么就必须要使用引用类型,也就是类class。其他情况下,参考如下:

使用值类型的情景:
•使用==运算符比较实例数据时。
•单独复制一份实例数据时。
•在多线程环境下操作数据时。

使用引用类型(比如class)的情景:
•当使用===运算符判断两个对象是否引用同一个实例时。
•需要创建一个共享的、可变的对象时。

上一篇下一篇

猜你喜欢

热点阅读