swift从零开始-10-类与结构体

2017-11-17  本文已影响10人  SPIREJ

1. 类和结构体对比
swift中类与结构体的共同处:

与结构体相比,类还有如下的附加功能:

2. 定义
通过关键字 classstruct 来分别表示类和结构体

class SomeClass {
    //
}

struct SomeStruct {
    //
}

示例

/*
 名为Resolution的结构体,描述一个显示器的像素分辨率
 包含width 和 heigth 的存储属性
 */
struct Resolution {
    var width = 0
    var heigth = 0
}

/*
 VideoMode 类,描述一个视屏显示器的特定模式
 */
class VideoMode {
    var resolution = Resolution()
    var interlaced = false
    var frameRate = 0.0
    var name: String?
}

3. 类和结构体实例
生成结构体和类实例的语法非常相似:使用初始化语法,即在结构体名或类名后面跟随一个括号

let someResolution = Resolution()
let someVideoMode = VideoMode()
print("the width of someResolution is \(someResolution.width)")
print("the width of someVideoMode is \(someVideoMode.resolution.width)")
//也可以用点语法为属性变量赋值
someVideoMode.resolution.width = 1080

//结构体类型的成员逐一初始化器
let aoc = Resolution(width: 640, heigth: 480)
print(aoc.width,aoc.heigth)

4. 结构体和枚举是值类型
值类型被赋予一个变量,常量或者本身被传递给一个函数的时候,实际操作的是其的拷贝
在swift中,所有的基本类型:整型,浮点型,布尔型,字符串,数组,字典都是值类型,并且都是以结构体的形式在后台所实现
在swift中,所有的结构体和枚举都是值类型。它们的实例,一级实例包含的任何值类型属性,在代码中传递的时候都会被复制

let hd = Resolution(width: 1920, heigth: 1080)
var cinema = hd

代码可以这么看:声明一个名为hd的常量,其值初始化为高清视屏分辨率Resolution的实例
声明一个名为cinema的变量其值为之前声明的cinema,但是在后台他们两个是完全不同的实例

5. 类是引用类型
初始化一个VideoMode类的实例

let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.frameRate = 25.0
tenEighty.name = "1080i"

因为类是引用类型,所以alsoTenEighty和tenEighty实际上是相同的VideoMode实例,所以改变了alsoTenEighty的属性值,tenEighty的也随之改变

let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0
print(tenEighty.frameRate)
//30.0

6. 恒等运算符

  1. 等价于(===)
  2. 不等价于(!==)

7. 类和结构体的选择
在你的代码中,你可以使用类和结构体来定义你的自定义数据类型。

然而,结构体实例总是通过值传递,类实例总是通过引用传递。这意味两者适用不同的任务。当你的在考虑一个工程项目的数据构造和功能的时候,你需要决定每个数据构造是定义成类还是结构体。

按照通用的准则,当符合一条或多条以下条件时,请考虑构建结构体:

结构体的主要目的是用来封装少量相关简单数据值。
有理由预计一个结构体实例在赋值或传递时,封装的数据将会被拷贝而不是被引用。
任何在结构体中储存的值类型属性,也将会被拷贝,而不是被引用。
结构体不需要去继承另一个已存在类型的属性或者行为。

合适的结构体候选者包括:

几何形状的大小,封装一个width属性和height属性,两者均为Double类型。
一定范围内的路径,封装一个start属性和length属性,两者均为Int类型。
三维坐标系内一点,封装x,y和z属性,三者均为Double类型。
在所有其它案例中,定义一个类,生成一个它的实例,并通过引用来管理和传递。实际中,这意味着绝大部分的自定义数据构造都应该是类,而非结构体。

var ages = ["A":23, "B":35, "C":18, "D":20]
var copyAges = ages

这个字典的键是String类型,值是Int类型,都是值类型,所以在拷贝时,两者都会被拷贝。赋值结束后,copyAges和ages成为两个相互独立的字典

copyAges["B"] = 22
print("ages B'age is \(ages["B"])")
//print ---> 35
var a = [1,2,3]
var b = a
var c = a
print("a[0] = \(a[0]), b[0] = \(b[0]), c[0] = \(c[0])")
//a[0] = 1, b[0] = 1, c[0] = 1

a[0] = 42
//测试与文档说的不一致--待定
print("a[0] = \(a[0]), b[0] = \(b[0]), c[0] = \(c[0])")
//a[0] = 42, b[0] = 1, c[0] = 1
//[42, 2, 3] [1, 2, 3] [1, 2, 3]
上一篇 下一篇

猜你喜欢

热点阅读