Swift中的类和结构体
1. 类和结构体对比
1.1 定义语法
你每次定义一个新类或者结构体的时候,实际上你是定义了一个新的Swift
类型。因此请使用UpperCamelCase
这种方式来命名(如SomeClass
和SomeStructure
等),以便符合标准Swift
类型的大写命名风格(如String
,Int
和Bool
)
定义类和结构体示例:
struct Resolution {
var width = 0
var height = 0
}
class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}
类和结构体实例:
let someResolution = Resolution()
let someVideoMode = VideoMode()
结构体类型的成员逐一构造器:
let vga = Resolution(width: 640, height: 480)
与结构体不同,类实例没有默认的成员逐一构造器。
1.2 结构体和枚举是值类型
值类型被赋予给一个变量、常量或者被传递给一个函数的时候,其值会被拷贝。
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
cinema.width = 2048
print(hd)
print(cinema)
// print "Resolution(width: 1920, height: 1080)"
// print "Resolution(width: 2048, height: 1080)"
枚举也是值类型。
在Swift
中,所有的基本类型:整数(Integer)、浮点数(floating-point)、布尔值(Boolean)、字符串(string)、数组(array)和字典(dictionary),都是值类型,并且在底层都是以结构体的形式所实现。
1.3 类是引用类型
与值类型不同,引用类型在被赋予到一个变量、常量或者被传递到一个函数时,其值不会被拷贝。因此,引用的是已存在的实例本身而不是其拷贝。
如果能够判定两个常量或者变量是否引用同一个类实例将会很有帮助。为了达到这个目的,Swift 内建了两个恒等运算符:
- 等价于(
===
) - 不等价于(
!==
)
1.4 类和结构体的选择
按照通用的准则,当符合一条或多条以下条件时,请考虑构建结构体:
- 该数据结构的主要目的是用来封装少量相关简单数据值。
- 有理由预计该数据结构的实例在被赋值或传递时,封装的数据将会被拷贝而不是被引用。
- 该数据结构中储存的值类型属性,也应该被拷贝,而不是被引用。
- 该数据结构不需要去继承另一个既有类型的属性或者行为。
1.5 字符串、数组、和字典类型的赋值与复制行为
Swift 中,许多基本类型,诸如String
,Array
和Dictionary
类型均以结构体的形式实现。这意味着被赋值给新的常量或变量,或者被传入函数或方法中时,它们的值会被拷贝。
Objective-C 中NSString
,NSArray
和NSDictionary
类型均以类的形式实现,而并非结构体。它们在被赋值或者被传入函数或方法时,不会发生值拷贝,而是传递现有实例的引用。
注意
以上是对字符串、数组、字典的“拷贝”行为的描述。在你的代码中,拷贝行为看起来似乎总会发生。然而,Swift 在幕后只在绝对必要时才执行实际的拷贝。Swift 管理所有的值拷贝以确保性能最优化,所以你没必要去回避赋值来保证性能最优化。