一、类和结构的异同
类和结构有一些相似的地方,它们都可以:
1. 定义一些可以赋值的属性;
2. 定义具有功能性的方法
3. 定义下标,使用下标语法
4. 定义初始化方法来设置初始状态
5. 在原实现方法上的可扩展性
根据协议提供某一特定类别的基本功能
1. 类还有一些结构不具备的特性:
2. 类的继承性
3. 对类实例实时的类型转换
4. 析构一个类的实例使之释放空间
上面的代码中,首先我们初始化了Name结构体的一个实例name1,然后初始化了Student类的实例,并对这个实例进行赋值。重点有以下几个方面
重点:
① 结构体的初始化可以像调用外部函数一样,通过属性名称指定初始值
② 属性的访问,在实例后加上“.”再加上属性名称即可访问属性
注意:
① 和结构不同,类实例不能够使用成员初始化方法,类的初始化会在后面专门介绍
② 和Objective-C不同,Swift能够直接设置一个结构属性的子属性
二、 结构和枚举类型是数值类型
数值类型是说当它被赋值给一个常量或者变量,或者作为参数传递给函数时,是完整地复制了一个新的数值,而不是仅仅改变了引用对象。
三 、类是引用类型
和结构类型不一样,类是属于引用类型,类的赋值只是用引用赋值
四、特征操作
判断2个对象是否指向同一个实例地址。需要用===和!==来判断
注意:
① 这并不是判断他们是否属于同一个类,如果b是 Student 类的另一个实例,则会不相等
② 不能使用==,编译器会报错
五、 如何选择使用类还是结构
在代码中可以选择类或者结构来实现你所需要的代码块,完成相应的功能。但是结构实例传递的是值,而类实例传递的是引用。那么对于不同的任务,应该考虑到数据结构和功能的需求不同,从而选择不同的实例。
一般来说,下面的一个或多个条件满足时,应当选择创建一个结构:
1. 结构主要是用来封装一些简单的数据值
2. 当赋值或者传递的时候更希望这些封装的数据被赋值,而不是被引用过去
3. 所有被结构存储的属性本身也是数值类型
4. 结构不需要被另外一个类型继承或者完成其它行为
在其它情况下,类会是更好的选择。也就是说一般情况下,数据都会定义为类
六、集合类型的赋值和复制操作
和Objective-C不一样,Swift中,数组Array和字典Dictionary是用结构来实现的,下面我们来看看他们具体有什么不一样的地方
如果字典中的键值是数值类型(结构或者枚举),它们在赋值的时候会同时被复制。相反,如果是引用类型(类或者函数),引用本身将会被复制,而不是类实例或者函数本身。字典的这种复制方式和结构相同。
1. 在将b用a赋值,在仅改变数组中值,不改变长度的情况下,数组不会进行复制,b会随着a改变。
2. 在改变长度的情况下,会进行复制,b将是一个新的数组,不会随着a改变
3. 数组独立
在数组赋值时,如果不想两个变量公用一个数组,可以用 unshare 关键字来使数组独立。
① 在调用 a . unshare () 方法时,会对a数组进行复制,然后让a指向复制数组。其他的指针还指向原对象
4. 判断2个数组是否指向同一数组地址
判断2个数组是否指向同一数组地址可以使用===和!==
如果对a或者b调用 unshare 之后。他们就不再指向同一数组地址了
5. 强制数组拷贝
如果想要将数组完整复制到一个新数组中,可以使用copy方法
①这时候a和b数组是2个不相关的数组,改变值不会对对方有任何影 响
② 如果你不确定你需要的数组是否是独立的,那么仅仅使用unshare就可以了。而copy方法不管当前是不是独立的,都会完整拷贝一次,哪怕这个数组已经是unshare的了。
类和结构有一些相似的地方,它们都可以:
1. 定义一些可以赋值的属性;
2. 定义具有功能性的方法
3. 定义下标,使用下标语法
4. 定义初始化方法来设置初始状态
5. 在原实现方法上的可扩展性
根据协议提供某一特定类别的基本功能
1. 类还有一些结构不具备的特性:
2. 类的继承性
3. 对类实例实时的类型转换
4. 析构一个类的实例使之释放空间
5. 引用计数,一个类实例可以有多个引用
1. 定义语法
struct Name{
let firstName = ""
let secondName = ""
}
class Student{
var name = Name()
var height = 0.0
var score = 0
}
let a = Student()
如代码所示,我们定义了一个结构体Name和一个类Student。在定义结构体和类的过程中有以下几点需要注意
注意:
① 基于书写规范,结构体和类的定义最好首字母大写
② 结构体和类的定义中,每个属性均需要给出默认值,否则编译器会报错
2. 访问属性以及结构类型初始化
let name1 = Name(firstName:"小",secondName:"本狼")
let a = Student()
a.name = name1;
a.height = 185
上面的代码中,首先我们初始化了Name结构体的一个实例name1,然后初始化了Student类的实例,并对这个实例进行赋值。重点有以下几个方面
重点:
① 结构体的初始化可以像调用外部函数一样,通过属性名称指定初始值
② 属性的访问,在实例后加上“.”再加上属性名称即可访问属性
注意:
① 和结构不同,类实例不能够使用成员初始化方法,类的初始化会在后面专门介绍
② 和Objective-C不同,Swift能够直接设置一个结构属性的子属性
二、 结构和枚举类型是数值类型
数值类型是说当它被赋值给一个常量或者变量,或者作为参数传递给函数时,是完整地复制了一个新的数值,而不是仅仅改变了引用对象。
struct Name{
var firstName = ""
var secondName = ""
}
var a = Name(firstName:"小",secondName:"笨狼")
var b = a
a.firstName = "大"
println(b.firstName) //输出:小
如上面的例子所示,结构类型的赋值是完整的创建一个新的值,原来对象改变不会对赋值对象产生任何影响
三 、类是引用类型
和结构类型不一样,类是属于引用类型,类的赋值只是用引用赋值
struct Name{
var firstName = ""
var secondName = ""
}
class Student{
var name = Name()
var height = 0
var score = 0
}
let a = Student()
let b = a
a.score = 98
println(b.score) //输出:98
如上面的例子所示,将a对b赋值,a的属性改变,b的属性也会随之改变,因为a和b是2个指针,他们都指向同一地址
四、特征操作
判断2个对象是否指向同一个实例地址。需要用===和!==来判断
let a = Student()
let b = a
if a === b{
println("a=b")
}else{
println("a != b")
} //输出 a=b
如上面的代码所示,a和b指向同一个实例,会输出a=b。
注意:
① 这并不是判断他们是否属于同一个类,如果b是 Student 类的另一个实例,则会不相等
② 不能使用==,编译器会报错
五、 如何选择使用类还是结构
在代码中可以选择类或者结构来实现你所需要的代码块,完成相应的功能。但是结构实例传递的是值,而类实例传递的是引用。那么对于不同的任务,应该考虑到数据结构和功能的需求不同,从而选择不同的实例。
一般来说,下面的一个或多个条件满足时,应当选择创建一个结构:
1. 结构主要是用来封装一些简单的数据值
2. 当赋值或者传递的时候更希望这些封装的数据被赋值,而不是被引用过去
3. 所有被结构存储的属性本身也是数值类型
4. 结构不需要被另外一个类型继承或者完成其它行为
在其它情况下,类会是更好的选择。也就是说一般情况下,数据都会定义为类
六、集合类型的赋值和复制操作
和Objective-C不一样,Swift中,数组Array和字典Dictionary是用结构来实现的,下面我们来看看他们具体有什么不一样的地方
1. 字典的赋值和复制操作
var ages = ["Peter": 23, "Wei": 35, "Anish": 65, "Katya": 19]
var copiedAges = ages
ages["Wei"] = 0
println(ages) //输出:[Anish: 65, Wei: 0, Peter: 23, Katya: 19]
println(copiedAges) //输出:[Anish: 65, Wei: 35, Peter: 23, Katya: 19]
由于字典是数值类型,赋值的时候会完整的赋值。
如果字典中的键值是数值类型(结构或者枚举),它们在赋值的时候会同时被复制。相反,如果是引用类型(类或者函数),引用本身将会被复制,而不是类实例或者函数本身。字典的这种复制方式和结构相同。
2. 数组的赋值和复制操作
和字典Dictionary类型比起来,数组Array的赋值和复制操作就更加复杂。Array类型和C语言中的类似,仅仅只会在需要的时候才会完整复制数组的值。
如果将一个数组赋值给一个常量或者变量,或者作为一个参数传递给函数,复制在赋值和函数调用的时候并不会发生。这两个数组将会共享一个元素序列,如果你修改了其中一个,另外一个也将会改变。
对于数组来说,复制只会在你进行了一个可能会修改数组长度操作时才会发生。包括拼接,添加或者移除元素等等。当复制实际发生的时候,才会像字典的赋值和复制操作一样。
var a = [1,2,3]
var b = a
a[0] = 5
println(a) //输出:[5, 2, 3]
println(b) //输出:[5, 2, 3]
a.append(4)
println(a) //输出:[5, 2, 3, 4]
println(b) //输出:[5, 2, 3]
如上面例子所示:
1. 在将b用a赋值,在仅改变数组中值,不改变长度的情况下,数组不会进行复制,b会随着a改变。
2. 在改变长度的情况下,会进行复制,b将是一个新的数组,不会随着a改变
3. 数组独立
在数组赋值时,如果不想两个变量公用一个数组,可以用 unshare 关键字来使数组独立。
var a = [1,2,3]
var b = a
a.unshare()
b[0] = 5
println(a) //输出:[1, 2, 3]
println(b) //输出:[5, 2, 3]
重点:
① 在调用 a . unshare () 方法时,会对a数组进行复制,然后让a指向复制数组。其他的指针还指向原对象
4. 判断2个数组是否指向同一数组地址
判断2个数组是否指向同一数组地址可以使用===和!==
var a = [1,2,3]
var b = a
if a === b{ }
注意:
如果对a或者b调用 unshare 之后。他们就不再指向同一数组地址了
5. 强制数组拷贝
如果想要将数组完整复制到一个新数组中,可以使用copy方法
var a = [1,2,3]
var b = a.copy()
注意:
①这时候a和b数组是2个不相关的数组,改变值不会对对方有任何影 响
② 如果你不确定你需要的数组是否是独立的,那么仅仅使用unshare就可以了。而copy方法不管当前是不是独立的,都会完整拷贝一次,哪怕这个数组已经是unshare的了。