类和结构体对比
Swift 中类和结构体有很多共同点。共同处在于:
定义属性用于储存值
定义方法用于提供功能
定义下标用于通过下标语法访问值
定义初始化器用于生成初始化值
通过扩展以增加默认实现的功能
符合协议以对某类提供标准功能
与结构体相比,类还有如下的附加功能:
继承允许一个类继承另一个类的特征
类型转换允许在运行时检查和解释一个类实例的类型
取消初始化器允许一个类实例释放任何其所被分配的资源
引用计数允许对一个类的多次引用
注意:结构体总是通过被复制的方式在代码中传递,因此请不要使用引用计数。
//类和结构体命名,类型 首字母大写, 属性和方法名首字母小写
//定义结构体 分辨率
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 someResoution is \(someResolution.width)")
// 输出:The width of someResoution is 0
//与 Objective-C 语言不同的是,Swift 允许直接设置结构体属性的子属性。
someVideoMode.resolution.width = 1280
print("The width of someVideoMode is now \(someVideoMode.resolution.width)")
// 输出:The width of someVideoMode is now 1280
//结构体类型的成员逐一初始化器 对成员变量初始化,而类实例没有此功能
let ss = Resolution(width: 640, height: 480)
print("ss.width:\(ss.width)")
/*
结构体和枚举是值类型
值类型被赋予给一个变量,常数或者本身被传递给一个函数的时候,实际上操作的是其的拷贝。
*/
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
cinema.width = 80
print("hd.width:\(hd.width) cinema.width:\(cinema.width)")
// 输出:hd.width:1920 cinema.width:80
//枚举
enum CompassPoint
{
case North, South, East, West
}
var currDir = CompassPoint.West
let rememberedDir = currDir
currDir = .East
if rememberedDir == .West
{
print("The remembered direction is still .West!")
}
//输出:The remembered direction is still .West!
//类是引用类型
let video = VideoMode()
video.resolution = hd
video.interlaced = true
video.name = "1080i"
video.frameRate = 25.0
let alsoVideo = video
alsoVideo.frameRate = 30.0
print("video.frameRate:\(video.frameRate)")
//输出:video.frameRate:30.0
/*恒等运算
"==="等价于 ,“!==” 不等价于 判定两个常量或者变量是否引用同一个类实例
*/
if video === alsoVideo {
print("video and alsoVideo refer to the same Resolution instance")
}
//video and alsoVideo refer to the same Resolution instance
类和结构体的选择
在你的代码中,你可以使用类和结构体来定义你的自定义数据类型。
然而,结构体实例总是通过值传递,类实例总是通过引用传递。这意味两者适用不同的任务。
按照通用的准则,当符合一条或多条以下条件时,请考虑构建结构体:
结构体的主要目的是用来封装少量相关简单数据值。
有理由预计一个结构体实例在赋值或传递时,封装的数据将会被拷贝而不是被引用。
任何在结构体中储存的值类型属性,也将会被拷贝,而不是被引用。
结构体不需要去继承另一个已存在类型的属性或者行为。
举例来说,以下情境中适合使用结构体:
几何形状的大小,封装一个width属性和height属性,两者均为Double类型。
一定范围内的路径,封装一个start属性和length属性,两者均为Int类型。
三维坐标系内一点,封装x,y和z属性,三者均为Double类型。
在所有其它案例中,定义一个类,生成一个它的实例,并通过引用来管理和传递。实际中,
这意味着绝大部分的自定义数据构造都应该是类,而非结构体。
字符串(String)、数组(Array)、和字典(Dictionary)类型的赋值与复制行为
Swift 中字符串(String),数组(Array)和字典(Dictionary)类型均以结构体的形式实现。
这意味着String,Array,Dictionary类型数据被赋值给新的常量或变量,或者被传入函数或方法中时,
它们的值会发生拷贝行为(值传递方式)。
Objective-C中字符串(NSString),数组(NSArray)和字典(NSDictionary)类型均以类的形式实现,
这与Swfit中以值传递方式是不同的。NSString,NSArray,NSDictionary在发生赋值或者传入函数(或方法)时,
不会发生值拷贝,而是传递已存在实例的引用。