uare的Rect实例,初始值原点是(0, 0),宽度高度都是10。如图所示蓝色正方形。
square的center属性可以通过点运算符(square.center)来访问,这会调用 getter 来获取属性的值。跟直接返回已经存在的值不同,getter 实际上通过计算然后返回一个新的Point来表示square的中心点。如代码所示,它正确返回了中心点(5, 5)。
center属性之后被设置了一个新的值(15, 15),表示向右上方移动正方形到如图所示橙色正方形的位置。设置属性center的值会调用 setter 来修改属性origin的x和y的值,从而实现移动正方形到新的位置。
简单setter声明
如果计算属性的 setter 没有定义表示新值的参数名,则可以使用默认名称newValue。下面是使用了便捷 setter 声明的Rect结构体代码:
struct AlternativeRect {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set {
origin.x = newValue.x - (size.width / 2)
origin.y = newValue.y - (size.height / 2)
}
}
}
只读计算属性
只有 getter 没有 setter 的计算属性就是只读计算属性。只读计算属性总是返回一个值,可以通过点运算符访问,但不能设置新的值。只读计算属性的声明可以去掉get关键字和花括号
struct Cuboid {
var width = 0.0, height = 0.0, depth = 0.0
var volume: Double {
return width * height * depth
}
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
println("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")
// 输出 "the volume of fourByFiveByTwo is 40.0"
属性观察
观察属性值的变化,当发生变化时实现自定义操作。可以为属性添加如下的一个或全部监视器:
- willSet在属性值变化前调用
- didSet在属性值变化后立即调用
willSet监视器会将新的属性值作为固定参数传入,在willSet的实现代码中可以为这个参数指定一个名称,如果不指定则参数仍然可用,这时使用默认名称newValue表示。
似地,didSet监视器会将旧的属性值作为参数传入,可以为该参数命名或者使用默认参数名oldValue。
注意:willSet和didSet监视器在属性初始化过程中不会被调用,他们只会当属性的值在初始化之外的地方被设置时被调用。
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
stepCounter.totalSteps = 896
// About to set totalSteps to 896
// Added 536 steps
StepCounter类定义了一个Int类型的属性totalSteps,它是一个存储属性,包含willSet和didSet监视器。
当totalSteps设置新值的时候,它的willSet和didSet监视器都会被调用,甚至当新的值和现在的值完全相同也会调用。
例子中的willSet监视器将表示新值的参数自定义为newTotalSteps,这个监视器只是简单的将新的值输出。
didSet监视器在totalSteps的值改变后被调用,它把新的值和旧的值进行对比,如果总的步数增加了,就输出一个消息表示增加了多少步。didSet没有提供自定义名称,所以默认值oldValue表示旧值的参数名。
注意:如果在didSet监视器里为属性赋值,这个值会替换监视器之前设置的值。
类型属性
实例属性是属于特定类型的实例的属性。每次创建该类型的新实例时,它都有它自己的一组属性值,与任何其他实例分离,也可以为类型本身定义属性,不管类型有多少个实例,这些属性都只有唯一一份。这种属性就是类型属性。
类型属性用于定义特定类型所有实例共享的数据,比如所有实例都能用的一个常量(就像 C 语言中的静态常量),或者所有实例都能访问的一个变量(就像 C 语言中的静态变量)。对于值类型(指结构体和枚举)可以定义存储型和计算型类型属性,对于类(class)则只能定义计算型类型属性。
值类型的存储型类型属性可以是变量或常量,计算型类型属性跟实例的计算属性一样定义成变量属性。
注意:跟实例的存储属性不同,必须给存储型类型属性指定默认值,因为类型本身无法在初始化过程中使用构造器给类型属性赋值。
类型属性语法
使用关键字static来定义值类型的类型属性,关键字class来为类(class)定义类型属性。下面的例子演示了存储型和计算型类型属性的语法
struct SomeStructure {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
// 这里返回一个 Int 值
}
}
enum SomeEnumeration {
static var storedTypeProperty = "Some value."
static var computedTypeProperty: Int {
// 这里返回一个 Int 值
}
}
class SomeClass {
class var computedTypeProperty: Int {
// 这里返回一个