类与结构是编程人员在代码中会经常用到的代码块。在类与结构中可以像定义常量,变量和函数一样,定义相关的属性和方法以此来实现各种功能。
和其它的编程语言不太相同的是,Swift不需要单独创建接口或者实现文件来使用类或者结构。Swift中的类或者结构可以在单文件中直接定义,一旦定义完成后,就能够被直接其它代码使用。
注意:一个类的实例一般被视作一个对象,但是在Swift中,类与结构更像是一个函数方法,在后续的章节中更多地是讲述类和结构的功能性。
1、类和结构的异同
类和结构有一些相似的地方,它们都可以:
定义一些可以赋值的属性;
定义具有功能性的方法
定义下标,使用下标语法
定义初始化方法来设置初始状态
在原实现方法上的可扩展性
根据协议提供某一特定类别的基本功能
更多内容可以阅读:属性,方法,下标,初始化,扩展和协议等章节
类还有一些结构不具备的特性:
类的继承性
对类实例实时的类型转换
析构一个类的实例使之释放空间
引用计数,一个类实例可以有多个引用
更多内容可以阅读:继承,类型转换,初始化自动引用计数
注意:结构每次在代码中传递时都是复制了一整个,所以不要使用引用计数
定义语法
类和结构拥有相似的定义语法,使用class关键词定义一个类,struct关键词定义结构。每个定义都由一对大括号包含:
class SomeClass {
// class definition goes here
}
struct SomeStructure {
// structure definition goes here
}
</div>
注意:在定义类和结构时,一般使用UpperCamelCase命名法来定义类和结构的名称,比如SomeClass和SomeStructure,这样也符合Swift其它类型的标准。而给属性和方法命名时,一般时候lowerCamelCase命名法,比如frameRate和incrementCount等。
下面是一个结构和一个类的定义示例:
struct Resolution {
var width = 0
var height = 0
}
class VideoMode {
var resolution = Resolution()
var interlaced = falsevar
frameRate = 0.0
var name: String?
}
</div>
上面的例子首先定义了一个叫Resolution的结构,用来描述一个像素显示的分辨率,它有两个属性分别叫width和height。这两个属性被默认定义为Int类型,初始化为0.
之后定义了一个叫VideoMode的类,为视频显示的显示方式。这个类有四个属性,第一个属性resolution本身又是一个结构,然后是另外两个属性。最后一个属性用到了可选字符串类型String?,表示这个属性可以存在,或者不存在为nil。
类和结构的实例
上面的两个定义仅仅是定义了结构Resolution和类VideoMode的整体样式,它们本身不是一个特定的分辨率或者显示方式,这时候就需要实例化这个结构和类。
实例化的语法相似:
let someResolution = Resolution()
let someVideoMode = VideoMode()
</div>
类和结构都使用实例语法来完成实例化。最简单的实例语法就是用两个括号()完成。在这种情况下定义的实例中的属性都会完成默认初始化。更多内容可以参考初始化一章。
访问属性
使用.语法就可以方便地访问一个实例的属性。在.语法中,在实例名之后加上(.)再加上属性名即可,不需要空格:
println("The width of someResolution is \(someResolution.width)")
// prints "The width of someResolution is 0"
</div>
在这个例子中,someResolution.width表示someResolution的width属性,返回了它的初始值0
也可以使用.语法连续地获取属性的属性,比如VideoMode中resolution属性的width属性
println("The width of someVideoMode is \(someVideoMode.resolution.width)")
// prints "The width of someVideoMode is 0"
</div>
使用这种方法不仅可以访问,也可以赋值:
someVideoMode.resolution.width = 1280
println("The width of someVideoMode is now \(someVideoMode.resolution.width)")
// prints "The width of someVideoMode is now 1280"
</div>
注意:和Objective-C不同,Swift能够直接设置一个结构属性的子属性,就像上面这个例子一样。
结构类型的成员初始化方法
每个结构都有一个成员初始化方法,可以在初始化的时候通过使用属性名称来指定每一个属性的初始值:
let vga = Resolution(width: 640, height: 480)
</div>
但是和结构不同,类实例不能够使用成员初始化方法,在初始化一章有专门的介绍。
2、结构和枚举类型是数值类型
数值类型是说当它被赋值给一个常量或者变量,或者作为参数传递给函数时,是完整地复制了一个新的数值,而不是仅仅改变了引用对象。
事实上读到这里你已经在前面几章见过数值类型了,所有Swift中的基础类型-整型,浮点型,布尔类型,字符串,数组和字典都是数值类型。它们也都是由结构来实现的。
在Swift中所有的结构和枚举类型都是数值类型。这意味这你实例化的每个结构和枚举,其包含的所有属性,都会在代码中传递的时候被完整复制。
下面的这个例子可以说明这个特性:
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
</div>
声明了一个常量hd,是Resolution的实例化,宽度是1920,高度是1080,然后声明了一个变量cinema,和hd相同。这个时候表明,cinema和hd是两个实例,虽然他们的宽度都是1920,高度都是1080。
如果把cinema的宽度更改为2048,hd的宽度不会变化,依然是1920
cinema.width = 2048
println("cinema is now \(cinema.width) pixels wide")
// prints "cinema is now 2048 pixels wide"
println("hd is still \(hd.width) pixels wide")
// prints "hd is still 1920 pixels wide"
</div>
这表明当hd被赋值给cinema时,是完整地复制了一个全新的Resolution结构给cinema,所以当cinema的属性被修改时,hd的属性不会变化。
下面的例子演示的是枚举类型:
enum CompassPoint {
case North, South, East, West
}
var currentDirection = CompassPoint.West
let rememberedDirection = currentDirection
currentDirection = .East
if rememberedDirection == .West {
println("The remembered direction is still .West")
}<