标签:
存储属性顾名思义就是存储在类和结构体中的常量或变量,当定义存储属性的时候可以给存储属性设定初始值,也可以在构造过程中设置值或改变值,
// 声明一个结构体 struct CustomRange { // 以下的代码定义了两个属性,一个为变量 一个为常量 并且都没有设置初始值 var firstValue: Int let length: Int } // 可以调用逐一构造方法给定初始值 var range = CustomRange(firstValue: 5, length: 6) // 因为firstValue是变量 可以在初始化之后修改值 range.firstValue = 6
注意:由于结构体是值类型,如果实例化一个常量结构体的话,不可以修改结构体中的变量属性,否则会报错:
let otherRange = CustomRange(firstValue: 3, length: 5) otherRange.firstValue = 5 // 此行代码会报错 因为otherRange被声明为常量,即使firstValue属性是变量也不可以修改
延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。当属性的值依赖于在实例的构造过程结束后才会知道具体值的外部因素时,或者当获得属性的初始值需要复杂或大量计算时,可以只在需要的时候计算它。声明延迟存储属性用<lazy>关键字,并且必须设置为变量(var)
// 例如有一个文件下载器 初始化这个下载器会消耗大量的时间和资源 class DataDownloader { var fileName: String? func start() { fileName = "swift.data" } } // 例如有一个文件管理者 class DataManager { // 因为之前假设下载器的初始化会消耗大量时间和资源 所以使用lazy lazy var downloader = DataDownloader() var search = [String]() } // 初始化了文件管理者 这时downloader还没有被调用 所以Downloader不会有值 var manager = DataManager() manager.search.append("some data") // 此时到了下面这行代码 downloader才会被初始化 manager.downloader.start()
除存储属性外,类、结构体和枚举可以定义计算属性。计算属性不直接存储值,而是提供一个 getter 和一个可选的 setter,来间接获取和设置其他属性或变量的值。
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() // 定义center属性 center属性不做任何存储 只是在get 和 set方法中对origin的值进行计算后修改 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 } // 下面的set方法和上面的等效 就是为新的值取了个名字 // set (newCenter) { // origin.x = newCenter.x - size.width / 2 // origin.y = newCenter.y - size.height / 2 // } } }
只有 getter 没有 setter 的计算属性就是只读计算属性。只读计算属性总是返回一个值,可以通过点运算符访问,但不能设置新的值。
class Rectangle { var length = 1.0, width = 2.0, height = 5.0 // var volume: Double { // get { // return length * width * height // } // } // 一般只有getter方法时可以像下面代码这么写,当然上面的也可以 var volume: Double { return length * width * height } } let rectangle: Rectangle = Rectangle() print("volume is \(rectangle.volume)") // 打印出: volume is 10.0
属性观察器监控和响应属性值的变化,每次属性被设置值的时候都会调用属性观察器,甚至新的值和现在的值相同的时候也不例外。可以为除了延迟存储属性之外的其他存储属性添加属性观察器,也可以通过重载属性的方式为继承的属性(包括存储属性和计算属性)添加属性观察器。一般不需要为非重载的计算属性添加属性观察器,因为可以通过它的 setter 直接监控和响应值的变化。
class Person { var name: String = "ASK" { willSet { print("the new name is \(newValue)") } didSet{ if name == "" { name = oldValue } print("did set the old name is \(oldValue) and the current name is \(name)") } } } let person = Person() person.name = "Alex" // 打印: the new name is Alex // did set the old name is ASK and the current name is Alex
注意: 如果在didset方法中为属性赋值的话 那么这个值会替换掉该观察器之前的值
如果将name属性赋为""(空串) ↓
person.name = "" // 打印: the new name is // did set the old name is ASK and the current name is ASK
在 C 或 Objective-C 中,与某个类型关联的静态常量和静态变量,是作为全局(global)静态变量定义的。但是在 Swift 编程语言中,类型属性是作为类型定义的一部分写在类型最外层的花括号内,因此它的作用范围也就在类型支持的范围内。
使用关键字static
来定义类型属性。在为类(class)定义计算型类型属性时,可以使用关键字class
来支持子类对父类的实现进行重写。下面的例子演示了存储型和计算型类型属性的语法:
class SomeClass { static var name = "class name" { willSet { print("static property will set name value") } } // 写成class代表子类可以重写 枚举可结构体不可以这么写 class var overrideProperty: Int { return SomeClass.name.characters.count } } print("name is \(SomeClass.name) length is \(SomeClass.overrideProperty)") SomeClass.name = "the some class" print("name is \(SomeClass.name) length is \(SomeClass.overrideProperty)") // 打印 1 name is class name length is 10 // 2 static property will set name value // 3 name is the some class length is 14
标签:
原文地址:http://www.cnblogs.com/Alex-sk/p/5176539.html