存储属性
struct FixedLengthRange { var firstValue: Int let length : Int } var rangeOfThreeItems = FixedLengthRange(firstValue: 0,length :3) // 该区间表示整数0,1,2 rangeOfThreeItems.firstValue = 6 // 该区间现在表示整数6,7,8
可以在定义存储属性的时候指定默认值,也可以在构造过程中设置或修改存储属性的值,甚至修改常量存储属性的值
常量和存储属性
struct FixedLengthRange { var firstValue: Int let length: Int } let rangeOfFourItems = FixedLengthRange(firstValue: 0,length: 4) // 该区间表示整数0,1,2,3 rangeOfFourItems.firstValue = 6 // 尽管 firstValue 是个变量属性,这里还是会报错
因为rangeOfFourItems声明成了常量(用let关键字),即使firstValue是一个变量属性,也无法再修改它了。
这种行为是由于结构体(struct)属于值类型。当值类型的实例被声明为常量的时候,它的所有属性也就成了常量。
延迟存储属性
class DataImporter { /* DataImporter 是一个将外部文件中的数据导入的类。 这个类的初始化会消耗不少时间。 */ var fileName = "data.txt" // 这是提供数据导入功能 } class DataManager { lazy var importer = DataImporter() var data = [String]() // 这是提供数据管理功能 } let manager = DataManager() manager.data.append("Some data") manager.data.append("Some more data") // DataImporter 实例的 importer 属性还没有被创建 print(manager.importer.fileName) // DataImporter 实例的 importer 属性现在被创建了 // 输出 "data.txt”
计算属性
struct Point { var x = 0.0,y = 0.0 } struct Size { var width = 0.0,height = 0.0 } struct Rect { 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 = Rect(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))") // 输出 "square.origin is now at (10.0,10.0)”
如果计算属性的 setter 没有定义表示新值的参数名,则可以使用默认名称newValue
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) } } }
读计算属性总是返回一个值,可以通过点运算符访问,但不能设置新的值。
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"
属性观察器
willSet观察器会将新的属性值作为固定参数传入,在willSet的实现代码中可以为这个参数指定一个名称,如果不指定则参数仍然可用,这时使用默认名称newValue表示。
类似地,didSet观察器会将旧的属性值作为参数传入,可以为该参数命名或者使用默认参数名oldValue。
类似地,didSet观察器会将旧的属性值作为参数传入,可以为该参数命名或者使用默认参数名oldValue。
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
类型属性
用static关键字定义类型属性实例如下:
struct SomeStructure { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { return 1 } } enum SomeEnumeration { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { return 6 } } class SomeClass { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { return 27 } class var overrideablecomputedTypeProperty: Int { return 107 } } print(SomeStructure.storedTypeProperty) SomeStructure.storedTypeProperty = "Another value" print(SomeStructure.storedTypeProperty) print(SomeEnumeration.computedTypeProperty) print(SomeClass.computedTypeProperty)