类和结构体对比
类和结构体是人们构建代码所用的一种通用且灵活的构造体。我们可以使用完全相同的语法规则来为类和结构体
定义属性(常量、变量)和添加方法,从而扩展类和结构体的功能。
Swift 并不要求你为自定义类和结构去创建独立的接口和实现文件。你所要做的是在 一个单一文件中定义一个类或者结构体,系统将会自动生成面向其它代码的外部接口。
类和结构体对比
Swift 中类和结构体有很多共同点。共同处在于:
• 定义属性用于存储值
• 定义方法用于提供功能
• 定义附属脚本用于访问值
• 定义构造器用于生成初始化值
• 通过扩展以增加默认实现的功能 • 实现协议以提供某种标准功能
与结构体相比,类还有如下的附加功能:
• 继承允许一个类继承另一个类的特征
• 类型转换允许在运行时检查和解释一个类实例的类型 • 解构器允许一个类实例释放任何其所被分配的资源
• 引用计数允许对一个类的多次引用
定义
类和结构体有着类似的定义方式。我们通过关键字 class 和 struct 来分别表示类和结构体,并在一对大括号中定 义它们的具体内容
以下是定义结构体和定义类的示例:
struct Resolution { var width = 0 var height = 0
}
class VideoMode {
var resolution = Resolution() var interlaced = false
var frameRate = 0.0
var name: String?
}
示例说明:在上面的示例中我们定义了一个名为 Resolution 的结构体,用来描述一个显示器的像素分辨率。这个结构体包含 了两个名为 width 和 height 的存储属性。存储属性是捆绑和存储在类或结构体中的常量或变量。当这两个属性 被初始化为整数 0 的时候,它们会被推断为 Int 类型。
在上面的示例中我们还定义了一个名为 VideoMode 的类,用来描述一个视频显示器的特定模式。这个类包含了 四个储存属性变量。第一个是 分辨率,它被初始化为一个新的 Resolution 结构体的实例,具有 Resolution 的 属性类型。新 VideoMode 实例同时还会初始化其它三个属性,它们分别是:
初始值为 false (意为“非隔行扫描 视频”)的 interlaced ;
回放帧率初始值为 0.0 的 frameRate ;
值为可选 String 的 name 。 name 属性会被 自动赋予一个默认值 nil,意为“没有 name 值”,因为它是一个可选类型。
类和结构体实例
生成结构体和类实例的语法非常相似:
let someResolution = Resolution() let someVideoMode = VideoMode()
结构体和类都使用构造器语法来生成新的实例。构造器语法的最简单形式是在结构体或者类的类型名称后跟随一 对空括号
属性访问
通过使用点语法(dot Syntax),你可以访问实例中所含有的属性,具体不多说了,应该都知道。示例:
someVideoMode.resolution.width = 1280
注意: 与 Objective-C 语言不同的是,Swift 允许直接设置结构体属性的子属性。上面的例子,就是 直接设置了 someVideoMode 中 resolution 属性的 width 这个子属性,以上操作并不需要重新设置 resolutio n 属性
结构体类型的成员逐一构造器
所有结构体都有一个自动生成的成员逐一构造器,用于初始化新结构体实例中成员的属性。新实例中各个属性的
初始值可以通过属性的名称传递到成员逐一构造器之中:
let vga = Resolution(width:640,height: 480) 与结构体不同,类实例没有默认的成员逐一构造器。
结构体和枚举是值类型
值类型被赋予给一个变量、常量或者本身被传递给一个函数的时候,实际上操作的是其的拷贝。
实际上,在 Swift 中,所有的基本类型:整数(Integer)、浮点 数(floating-point)、布尔值(Boolean)、字符串(string)、数组(array)和字典(dictionary),都是值 类型,并且都是以结构体的形式在后台所实现。
类是引用类型
与值类型不同,引用类型在被赋予到一个变量、常量或者被传递到一个函数时,操作的是引用,其并不是拷贝。因此,引用的是已存在的实例本身而不是其拷贝。具体不多说
因为类是引用类型,有可能有多个常量和变量在后台同时引用某一个类实例。(对于结构体和枚举来说,这并不成立。因为它们作为值类型,在被赋予到常量、变量或者传递到函数时,其值总是会被拷贝。)
为了判断两个常量或变量引用的是否是同一个实例,swift创建了新的恒等运算符:
• 等价于 ( === )
• 不等价于 ( !== )
请注意 “等价于” (用三个等号表示,===) 与 “等于” (用两个等号表示,==)的不同:
• “等价于”表示两个类类型(class type)的常量或者变量引用同一个类实例。
• “等于”表示两个实例的值“相等”或“相同”,判定时要遵照类设计者定义定义的评判标准,因此相比 于“相等”,这是一种更加合适的叫法。
struct Resolution {
var width = 0
var height = 0
}
class VideoModel {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name:String?
}
func objectDemoWithClassAndStructe(){
//1 实例定义
var someResolution = Resolution()
let someVideoModel = VideoModel()
print(someVideoModel)
//2 属性访问
someResolution.width = 320
//3 结构体类型的成员逐一构造器
let newResolution = Resolution(width: 320,height: 480)
print(newResolution) //Resolution(width: 320,height: 480)
//4 结构体是值类型
var copyResolution = newResolution
copyResolution.height = 560
print(newResolution) //Resolution(width: 320,height: 480)
print(copyResolution)//Resolution(width: 320,height: 560)
//5 类是引用类型
let originVidelModel = VideoModel()
originVidelModel.resolution = someResolution
print(originVidelModel.resolution)
let copyVideoModel = originVidelModel
copyVideoModel.resolution = newResolution
print(originVidelModel.resolution)
print(copyVideoModel.resolution)
if originVidelModel === copyVideoModel {
print("originVidelModel and copyVideoModel has the same VideoModel instance")
}
//print:originVidelModel and copyVideoModel has the same VideoModel instance
}
指针
如果你有 C,C++ 或者 Objective-C 语言的经验,那么你也许会知道这些语言使用指针来引用内存中的地 址。一个 Swift 常量或者变量引用一个引用类型的实例与 C 语言中的指针类似,不同的是并不直接指向内存中的 某个地址,而且也不要求你使用星号(*) 来表明你在创建一个引用。Swift 中这些引用与其它的常量或变量的定 义方式相同。
类和结构体的选项
在你的代码中,你可以使用类和结构体来定义你的自定义数据类型
然而,结构体实例总是通过值传递,类实例总是通过引用传递。这意味着两者适用不同的场景。
按照通用的准则,当符合一条或多条以下条件时,可以考虑构建结构体:
1.结构体的主要目的是用来封装少量相关简单数据值
2.有理由预计一个结构体实例在赋值或传递时,封装的数据将会被拷贝而不是被引用
3.任何在结构体中存储的值类型属性,也将会被拷贝,而不是被引用。
4.结构体不需要去继承另一个以存在的类型的属性或行为。
在所有其它案例中,定义一个类,生成一个它的实例,并通过引用来管理和传递。实际中,这意味着绝大部分的
自定义数据构造都应该是类,而非结构体。
字符串,数组和字典的赋值与复制
Swift 中   和 字典(Dictionary) 类型均以结构体的形式实现。这意味着String,Array,Dictionary类型数据被赋值给新的常量或变量,或者被传入函数或方法中时,它们的值会发生拷贝行 为(值传递方式)。
字符串(String),数组(Array)、Objective-C中 字符串(NSString),数组(NSArray) 和 字典(NSDictionary) 类型均以类的形式实现,这 与Swfit中以值传递方式是不同的。NSString,NSArray,NSDictionary在发生赋值或者传入函数(或方 法)时,不会发生值拷贝,而是传递已存在实例的引用。
swift初学,留下笔记,不喜勿喷,欢迎交流