Swift学习笔记 ---Properties

来源:互联网 发布:零基础学算法可行 编辑:程序博客网 时间:2024/06/16 22:55

一.存储属性

  存储属性是一个变量或者是一个常量,其被放置在类或者结构体的定义中。我们可以给存储属性设置一个默认值。在初始化期间我们可以改变存储属性的值,即使存储属性是 let。

常量结构体的存储属性

  如果你生成一个结构体的实例对象并把这个对象复制给一个常量,那么结构体中的所有存储属性都不能改变,包括 var

懒惰的存储属性

  懒惰的存储属性只有在它第一次被用的时候才会被初始化。声明一个懒惰的存储属性必须在他的声明前加上 lazy。同时要注意只有 var 才可以是懒惰存储属性。因为 let 在初始化完成前必须有个初始化的值。当一个属性的初始化值是复杂的或者初始化需要的代价非常高的时候,我们可以利用这个特性,使我们只有在用的时候才初始化。  如果一个 lazy 存储属性没有被初始化,当多线程同时访问的时候无法保证只被初始化了一次。

存储属性和实例变量

  如果你有 OC 的经验,你可能知道它提供两种方式去存储值和引用。对于一个属性之外,你能用实例变量作为后备的存储,来存储值。Swift 统一了这些概念进入单一的属性宣称。Swift 属性没有相应的实例变量,和后备存储区来对一个变量进行直接的存储。这个方法避免了值是如何在不同的上下文中被存储的混淆和简化了属性的宣称。

二.计算属性

   除了存储属性之外,类、结构体和枚举类型都还能定义计算属性。它没有实际上存储一个值,而是提供一个 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()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.centersquare.center = Point(x: 15.0, y: 15.0)    print("square.origin is now at (\(square.origin.x), \(square.origin.y))")// Prints "square.origin is now at (10.0, 10.0)"

简便设置Setter

 如果一个计算属性的 setter 方法没有定义一个新值的名字,那么一个默认值 newValue 将会被用于 setter 方法。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)    }}}var rect = AlternativeRect(origin: Point(x: 10, y: 10), size: Size(width: 5,height: 5))rect.center = Point(x: 3, y: 3);print("\(rect.origin.x)");//0.5

只读计算属性

  只读计算属性只有getter 方法没有 setter 方法。你声明的计算属性必须是 var 类型的包括只读计算属性。let 只能被用在常量属性,表示一旦实例完成初始化,它的值不能被修改。  你能通过移除 key 关键字和它的{}来简化定义一个只读属性的语法。struct Cuboid {var width = 0.0, height = 0.0, depth = 0.0var 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)")// Prints "the volume of fourByFiveByTwo is 40.0"

属性观察者

  属性观察者能够观察属性的改变,并对改变做出回应。只要一个属性的值被改变,属性观察者能够立即做出回应,即使新值和旧值是相同的。  除了懒惰存储属性外,你可以为任何存储属性设置观察者。你也可以给父类的存储属性添加观察者,者只需要我们覆盖父类的属性。   你可以选择定义下面任何一个或者全部的观察者:   1)willSet    属性值被改变之前,调用这个方法。   2)didSet     属性值被改变之后,调用这个方法。  如果你实现了 willSet 观察者,它传送新值作为一个不可变的参数。你能定义这个参数名,也可以用默认的参数名 newValue;  相似,didiSet 有个默认的参数名叫做 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如果你传送一个属性作为一个 in-out 参数,willSet 和 didSet 永远被调用。应为属性首先被复制进入函数(copy-in)函数结束后将会被赋值给属性(copy-out);

全局变量和局部变量

 以上所述的计算和观测属性值变化的方法也可应用于全局变量和局部变量。全局变量不被定义在任何方法,函数,块或者其他种类的上下文。局部变量正好相反。 全局变量和局部变量可以是存储变量。存储变量提供一个可以设置一个值或者取回一个值的方法啊 你也可以定义计算变量或者可以为一个存储变量定义一个观察者。 全局常量和变量都是懒惰的,并且他们不用加 lazy修饰语。

类型属性

 实例属性是属于某一特定类型的实例的属性。每当您创建该类型的新实例时,它会设置属于它自己的属性值,从而可以从其他的实例里区分出来。 我们可以定义一个属性,这个属性属于这个类。不管里创建了多少个类型的实例,这个属性只有一个,不会被复制。这就是类型属性。 存储类型属性可以是变量或者常量,而计算类型属性必须是变量。 你必须给存储类型属性一个初始化值,应为它没有初始化的方法来设置它的值。并且只有我们第一次访问它时,它才初始化。 类型属性定义语法 我们可以通过加 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)// Prints "Some value."    SomeStructure.storedTypeProperty = "Another value."print(SomeStructure.storedTypeProperty)// Prints "Another value."print(SomeEnumeration.computedTypeProperty)// Prints "6"print(SomeClass.computedTypeProperty)// Prints "27"
0 0
原创粉丝点击