类和结构体
类和结构体在C++中差异就很小的东西,到了swift依然差异很小,但又不会像C++那样可以用struct取代class关键字(当且仅当我们不care public,protected,private字段的时候)。
swift和大多数语言不太一样,我们可以把class和结构体等定义在一个单独的文件里,然后在其它文件里直接用就行了,不需要include也不需要import,对于这点来说,可以减少因为引入过多的不必要的头文件导致的编译速度急剧下降的问题。
在swift中,class与struct不同的地方在于,class多了一些特性:
1. 类可以继承
2. 运行时可以做类型转换
3. 有析构函数
4. 引用计数
从上面的几个特性中可以分析出,struct没有引用计数的话,要么它只有一个实例,要么它每次使用的时候都是一份新的拷贝。实际上,是每次用的时候,都是一个新的拷贝。
类定义方法:
class MyClass {
//类的成员
var typeName = “class"
}
结构体定义方法:
struct MyStruct {
//结构体的成员
var typeName = “struct"
}
类和结构体,都是一定自定义数据类型,所以swift建议类与结构体的名字首字母都要大写。
没有了 public, protected, private的关键字,一切就像C++里面的struct那么开心,于是我们可以全用”.”来直接访问成员变量,自由无约束:
var myFirstClassInstance = MyClass() //定义一个变量,它是MyClass类型的实例
println(myFirstClassInstance.typeName) //使用. 来访问这个实例的成员属性
结构体有个特别之处, 在初始化的时候,可以把成员的值直接写在参数里面,而类不能:
var myFirstStructInstance = MyStruct(typeName: “my first struct”)
值类型(Value Type)
在定义变量,常量,或者是做为函数的参数传递的时候,都会复制一份,这种叫Value Type, 所谓的值传递。
还有一种叫做引用传递,和上面的字义类似,只不过它并不会复制,而是一个引用。
类是引用类型。
结构体,枚举以及所有的swift中的基本数据类型,包括Array, Dictionary等,全部都是值传递的。
//差点就吓尿了,Array, Dictionary也是值传递!!! 但是还是先淡定一点,也许swift有相关优化?也许吧。。
//因为Array 和 Dictionary是struct。。。
请我们来验证一下:
var myStruct1 = MyStruct()
var myStruct2 = myStruct1
myStruct1.typeName = “Hello”
println(myStruct2.typeName)
var myClass1 = MyClass()
var myClass2 = myClass1
myClass1.typeName = “world”
println(myClass2.typeName)
通过例子的结果,可以得到上面的说法,class是引用传递, struct是值传递 (当然要做更多的测试才能充分说明这一点,但这里就先不试了)
身份操作符 (Identity Operators, 叫标识操作符也可以)
swift 提供了这样两个操作符: === 和 !==,用来判断两个变量或者常量,是否同时引用的是同一个类的实例
比如上面的 myClass1和myClass2 我们就可以用这种方法来检测:
println(“myClass1 and myClass2 are the same instance of MyClass: \(myClass1 === myClass2)”)
对于到底什么时候用struct,什么时候用class,官方文档里说了一堆废话,总结一句话:在你需要用struct的时候用struct, 需要用class的时候用class。因为struct和class的区别,在本篇一开始的时候已经说了,那么在有区别的时候,自然选择就出现了。
前面说了,Array和 Dictionary都是 struct,那么在每次赋值和作为函数参数传递的时候,就应该是拷贝一份,然而,有一个实验,却得到了个让人惊呆的结果:
var myDictionary = [1:”1”, 2:”2”, 3:”3”]
var myDictionaryCopy = myDictionary
myDictionary[1] = “8”
println(myDictionaryCopy[1]) //得到结果是 1
var myArray = [1, 2, 3]
var myArrayCopy = myArray
myArray[1] = 8
println(myArrayCopy[1]) // 得到结果是8.......... 这行为与预期不符啊!!!!!!!
println(myArray === myArrayCopy) //得到false!!!!尼玛,既然是false,swift你为毛要改 myArrayCopy的值!!!!
不是说好的 Array和 Dictionary都是struct吗? 为毛在这个实验中,出现了两种截然不同的结果!!!
原来swift对Array单独做了优化,只有在必要的时候才为他们分配一份拷贝,这尼玛黑盒黑的好!
Array只有在数组长度变化的时候,才做拷贝。
这样的说法让人背后一阵冷汗,太多的黑盒让人不敢下手啊。。。。幸好,苹果的工程师也出了一身冷汗,为此,他们为我们提供了稍白盒的方法:
1. unshare()
myArrayCopy.unshare() // 写在 var myArryCopy = myArray下面一行啊
这样就可以让我们的myArray[1]不被改写
2. copy
var myArrayCopy = myArray.copy()
这两种方法还是稍有区别的,unshare() 其实并没有直接复制一个新的数组,但在必要时,他会复制一个新的,比如值的改变。而copy() 是直接就复制一份新的出来。