1. 相比较于Java,Swift中属性颇有意思,有不少分类:存储属性、计算属性和类型属性等等。app
2. 存储属性spa
存储属性:一个存储属性就是存储在特定类或结构体的实例里的一个常量或变量,存储属性能够是变量存储属性(用关键字var
定义),也能够是常量存储属性(用关键字let
定义)。code
若是建立了一个结构体的实例并赋值给一个常量,则没法修改实例的任何属性,即便定义了变量存储属性,代码以下:blog
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4) // 该区间表示整数0,1,2,3 rangeOfFourItems.firstValue = 6 // 尽管 firstValue 是个变量属性,这里仍是会报错
2.1 延迟存储属性get
延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用lazy
来标示一个延迟存储属性。必须将延迟存储属性声明成变量(使用var
关键字),由于属性的值在实例构造完成以前可能没法获得。而常量属性在构造过程完成以前必需要有初始值,所以没法声明成延迟属性。it
当属性的值依赖于在实例的构造过程结束前没法知道具体值的外部因素时,或者当属性的值须要复杂或大量计算时,能够只在须要的时候来计算它,这时候咱们可使用延迟存储属性。代码以下:io
class DataImporter { var fileName = "data.txt" } class DataManager { lazy var importer = DataImporter() var data = [String]() } let manager = DataManager() manager.data.append(" new data")
imprter 前面的关键字是lazy,是延迟存储属性,DataManager
也可能不从文件中导入数据。因此当DataManager
的实例被建立时,不必建立一个DataImporter
的实例,更明智的是当用到DataImporter
的时候才去建立它。class
2.2 计算属性import
除存储属性外,类、结构体和枚举能够定义计算属性,计算属性不直接存储值,而是提供一个 getter 来获取值,一个可选的 setter 来间接设置其余属性或变量的值。代码以下:监控
struct Point { var x = 0.0 , y = 0.0 } struct Size { var width = 0.0 , height = 0.0 } struct Rec { 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(newCenter){ origin.x = newCenter.x - (size.width / 2) origin.y = newCenter.y - (size.height / 2) } } } var square = Rec(origin: Point(x: 0.0, y: 0.0), size: Size (width : 10.0 , height : 10.0)) let initialSquareCenter = square.center square.center = Point(x : 15.0 , y: 15.0) print("square.origin is now at (\(square.origin.x), \(square.origin.y))")
Rec
提供了一个名为center
的计算属性。Rec
的计算属性center
提供了自定义的 getter 和 setter 来获取和设置矩形的中心点,就像它有一个存储属性同样。
2.3 只读计算属性
只有 getter 没有 setter 的计算属性就是只读计算属性。只读计算属性老是返回一个值,能够经过点运算符访问,但不能设置新的值。代码以下:
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) print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)") // 输出 "the volume of fourByFiveByTwo is 40.0" //只读计算属性的声明能够去掉get关键字和花括号
3. 属性观察器
属性观察器监控和响应属性值的变化,每次属性被设置值的时候都会调用属性观察器,甚至新的值和如今的值相同的时候也不例外。能够为属性添加以下的一个或所有观察器:
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
4. 类型属性
实例的属性属于一个特定类型实例,每次类型实例化后都拥有本身的一套属性值,实例之间的属性相互独立。也能够为类型自己定义属性,无论类型有多少个实例,这些属性都只有惟一一份。这种属性就是类型属性。值类型的存储型类型属性能够是变量或常量,计算型类型属性跟实例的计算属性同样定义成变量属性。
4.1 类型属性语法
使用关键字static
来定义值类型的类型属性,类(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 {
static var computedTypeProperty: Int { // 这里返回一个 Int 值 } }
4.2 获取和设置类型属性的值
跟实例的属性同样,类型属性的访问也是经过点运算符来进行,可是,类型属性是经过类型自己来获取和设置,而不是经过实例。好比:
print(SomeClass.computedTypeProperty) // 输出 "42" print(SomeStructure.storedTypeProperty) // 输出 "Some value." SomeStructure.storedTypeProperty = "Another value." print(SomeStructure.storedTypeProperty) // 输出 "Another value.”