PART_A 类&结构体对比
- 共同点
- 定义属性:存储值
- 定义方法:提供功能
- 定义附属脚本:访问值
- 定义构造器:生成初始化值
- 通过扩展增加默认实现的功能
- 实现协议以提供某种标准功能
- 类的附加功能
- 继承允许一个类继承另一个类的特征
- 类型转换允许在运行时检查和解释一个类实例的类型
- 析构器允许一个类实例释放任何其所被分配的资源
- 引用计数允许对一个类的多次引用(结构体总是通过被复制的方式在代码中传递,不使用引用计数)
- 语法格式
// 结构体
struct Resolution {
// 当赋值 0 时,类型推断 wdith 为 Int 类型
var width = 0
var height = 0
}
// 类
class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}
- 实例创建
let demoResolution = Resolution()
let demoVideoMode = VideoMode()
- 属性访问&变量属性赋值
-
对象.属性名
-
对象.属性名 = 值
- 结构体类型的成员逐一构造器
- 所有结构体的新实例中各属性的初始值可通过属性的名称传递到成员逐一构造器中
`let vga = Resolution(width: 640, height: 480)`
PART_B 结构体和枚举是值类型
- 所有基本类型(整型Integer、浮点型Float、布尔型Boolean、字符串String、数组Array、字典Dictionary)、枚举、结构体都是值类型. 赋值时仅为拷贝副本
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
cinema.width = 2048
// cinima.width 值为 2048, hd.width 值为 1920
- 类是引用类型:引用的是已存在的实例本身而不是其拷贝
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0
let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0
// tenEighty.frameRate 值为 30.0
需要注意的是 tenEighty 和 alsoTenEighty 被声明为常量而不是变量. 然而你依然可以改变 tenEighty.frameRate 和 alsoTenEighty.frameRate,因为 tenEighty 和 alsoTenEighty 这两个常量的值并未改变. 它们并不“存储”这个 VideoMode 实例,而仅仅是对 VideoMode 实例的引用. 所以,改变的是被引用的 VideoMode 的 frameRate 属性,而不是引用 VideoMode 的常量的值
- 恒等运算:
===
、==
-
===
:两个类类型的常量或变量引用同一个类实例 -
==
:两个实例的值相等
- 指针
PART_C 类和结构体的选择
- 大部分场景还是需要定义类,生成实例,通过引用来管理和传递
- 结构体场景
- 该数据结构的主要目的是封装少量相关简单数据值
- 有理由预计该数据结构的实例在被赋值或传递时,封装的数据将会被拷贝而不是被引用
- 该数据结构中存储的值类型属性,也应该被拷贝,而不是被引用
- 该数据结构不需要去继承另一个既有类型的属性或者行为
如定义几何形状:长宽高、三维坐标系内一点:xyz等
补充
1…Swift
String
、Array
、Dictionary
以结构体的形式实现,即被赋值给新的常量或变量、或被传入方法中时,其值会被拷贝2…OC 中
NSString
、NSArray
、NSDictionary
类型均以类的形式实现,其不会发生值拷贝,而是传递现有实例的引用