类和结构体
可以通过使用常量、变量和函数完全相同的语法来定义属性和方法向类和结构添加功能。
Swift不需要为自定义类和结构创建单独的接口和实现文件,只需要在单个文件中定义一个类或结构体Swift会自动形成对其他代码可用的外部接口。
## 比较类和结构体 类和结构体的共同之处:
- 定义属性以存储值
- 定义方法以提供功能
- 定义下标使用下标语法提供对其值的访问
- 定义初始化器以设置其初始状态
- 扩展默认实现的功能
- 遵循协议以提供某种特定功能
类具有的附加功能:
- 继承另一个类的特性
- 类型转换使得在运行时检查和解释类实例的类型
- 析构器以释放其内存
- 引用计数允许对类实例的多个引用
注意
结构体是值类型,且没有引用计数,类是引用类型。
## 定义语法 类和结构体定义语法类似,分别使用**class**和**struct**关键字。
class SomeClass {
// class definition goes here
}
struct SomeStructure {
// structure definition goes here
}
注意
类和结构体的类型名采用首字母大写的驼峰命名法,属性和方法采用小写的。
类和结构体的定义示例:
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()
类和结构体创建实例都使用初始化器,初始化器的最简单形式是使用类或结构体的类型名,后跟空括号。这样会将所有属性初始化为默认值。
访问属性
使用点语法访问实例的属性。
print("The width of someResolution is (someResolution.width)")
// Prints "The width of someResolution is 0"
Swift可以直接设置结构属性的子属性:
print("The width of someVideoMode is (someVideoMode.resolution.width)")
// Prints "The width of someVideoMode is 0"
使用点语法给变量属性设置新值:
someVideoMode.resolution.width = 1280
print("The width of someVideoMode is now (someVideoMode.resolution.width)")
// Prints "The width of someVideoMode is now 1280"
结构体类型的成员初始化器
所有结构体会自动生成一个成员初始化器,通过名称将实例的属性的初始化值传递给成员初始化器:
let vga = Resolution( 640, height: 480)
而类结构不生成默认的成员初始化器。
## 结构体和枚举是值类型 值类型是将值分配给变量或常量或将其传递给函数时复制其值的类型,改变其中一个而不会影响另一个。
Swift中的所有基本数据类型都是值类型,包括结构体和枚举。
说明结构体是值类型的示例:
let hd = Resolution( 1920, height: 1080)
var cinema = hd
cinema.width = 2048
print("cinema is now (cinema.width) pixels wide")
// Prints "cinema is now 2048 pixels wide"
print("hd is still (hd.width) pixels wide")
// Prints "hd is still 1920 pixels wide"
说明枚举是值类型的示例:
enum CompassPoint {
case north, south, east, west
}
var currentDirection = CompassPoint.west
let rememberedDirection = currentDirection
currentDirection = .east
if rememberedDirection == .west {
print("The remembered direction is still .west")
}
// Prints "The remembered direction is still .west"
## 类是引用类型 当引用类型被分配给变量或常量或将其传递给函数时,不会复制引用类型,而是直接使用原实例的引用,这意味着修改其中一个值会直接反映到另一个值。
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0
let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0
print("The frameRate property of tenEighty is now (tenEighty.frameRate)")
// Prints "The frameRate property of tenEighty is now 30.0"
上述的类实例都分配给了常量,修改实例的属性对常量本身的值无影响,只是改变内部的属性,未修改其引用。
等于运算符
使用等于运算符判断两个常量或变量是否为相同的类实例,即同一个引用,有两个相等运算符:
- 想等 (===)
- 不想等 (!==)
`
if tenEighty === alsoTenEighty {
print("tenEighty and alsoTenEighty refer to the same VideoMode instance.")
}
// Prints "tenEighty and alsoTenEighty refer to the same VideoMode instance."
指针
C和Objective-C语言中使用指针来引用内存地址,而Swift中引用某个引用类型的实例与指针类似,但不是直接指向内存地址的指针,创建引用也不需要使用星号(*)。
## 选择类与结构体 使用类和结构体来定义复杂的自定义数据类型。
值类型和引用类型意味着结构体和类适合于不同类型的任务,依据以下原则考虑将一个数据类型定义为一个结构体:
- 结构体的主要目的是封装一些相对简单的数据值。
- 在分配或传递该实例时,期望封装的值将被复制会更加合理,而不是引用。
- 由结构体存储的任何属性本身都是值类型,也将被复制。
- 结构体不需要从另一个现有类型继承属性或方法。
以下为使用结构体的一些好的例子:
- 几何形状的大小,封装了均为Double类型的width属性和height属性。
- 代表一系列值的范围,封装了均为Int类型的start属性和length属性。
- 3D坐标系统的一个点,封装了均为Double类型的x,y和z属性。
以上原则说明,封装的属性都是数值类型时通常选择结构体。
在所有其他条件下,定义为一个类,并创建要通过引用进行管理和传递的类的实例。,这意味着大多数自定义数据结构应该是类而不是结构。