类和结构体很像,其比较不同的一点就是:类是引用类型,结构体是值类型
其共同点:
- 都可以定义属性来存储值
- 都可以定义方法
- 都可以定义下标(
subscript
),使用下标来访问它们的值 - 都可以通过构造器初始化,结构体有一个默认的自动生成的成员逐一构造器,可用于初始化结构体实例中的成员
- 都可以通过扩展增强功能
- 都可以遵循协议以提供某种标准功能
类还有其它的功能:
- 类可以继承
- 类型转换允许运行时检查和解释一个类实例的类型
- 类存在析构器(
deinit
), 可用来释放资源 - 引用计数允许对一个类的多次引用,结构体总是通过被复制的方式在代码中传递,不使用引用计数
另外OC在创建类的时候会得到2个文件:一个接口文件(.h文件), 一个实现文件(.m文件)
1.值引用和类型引用
提到值引用和类型引用,一般都会提到值类型和引用类型
swift中所有的基础类型都是值类型,值类型有:需要特别说明的是,其它语言中的数组等一般都是引用类型,但是swift中的 Array
, Dictionary
, Set
都是使用结构体定义的
- Int , Float, Double
- String
- Bool
- Array
- Dictionary
- Set
- Enum
- Structure
值引用赋值给另一个变量的时候,是以拷贝的形式进行赋值的,修改赋值的值,不会影响原来的值。值引用并不是完全的复制,底层依旧是某种指针,因此不必担心值引用性能问题
引用类型存储在堆中,指针地址存在在栈中,栈中的地址会指向堆中存储的值
OC中 NSString
, NSArray
, NSDictionary
都是以类的形式出现,因此是引用类型
2.结构体(Structure)
定义方式,关键词 struct
struct SomeStructure {
// 结构体
}
示例:
struct Resolution {
// width, height 都是存储属性
// 存储属性是存储在类或者结构体中的变量或者常量
var width = 0
var height = 0
}
结构体默认构造器
所有结构体都自动生成一个默认的构造器,用来初始化新结构体实例中成员的属性, 类实例不存在默认构造器
// 新实例中各个属性的初始值可以通过属性的名称传递到构造器中
let vga = Resolution(width: 640, height: 480)
结构体和枚举一样都是值类型
通过拷贝的方式进行引用
let hd = Resolution(width: 1920, height: 1080)
print(hd.width) // 1920
var cinema = hd
cinema.width = 3244
print(cinema.width) // 3244
// hd 并不会发生变化
print(hd.width) // 1920
3.类(class)
类使用关键词 class
定义
class SomeClass {
// 类的定义
}
示例:
struct Resolution {
var width = 0
var height = 0
}
class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}
// 使用
let hd = Resolution(width: 1920, height: 1080)
let video = VideoMode()
video.resolution = hd
video.interlaced = true
video.name = "1080i"
video.frameRate = 25.0
恒等运算符
因为类是引用类型的,有时多个常量和变量在幕后同时应用一个类实例,swift内建了2个恒等运算符,和JS中类似,因为swift是强类型,这个恒等比JS中要好用
注意这2个操作符只能针对引用类型,不能在值类型上使用
- 等价于(
===
) - 不等价于(
!==
)
let anotherVideo = video // 将上面实例化的video赋值给另一个常量
if anotherVideo === video {
print("引用的完全是相同的")
}
// 引用的完全是相同的
4.类和结构体如何选择
满足下面条件中的1条或者多条,建议使用结构体,其余情况使用类:
- 该数据结构主要用来封装少了的相关简单数据值
- 有理由预计该数据结构的实例在被赋值或传递时,封装的数据将会被拷贝而不是被引用
- 该数据结构中存储的值类型属性,也应该被拷贝,而不是被引用
- 该数据结构不需要去集成另一个既有类型的属性或行为