Swift(十一、属性)

来源:互联网 发布:iphone清理缓存软件 编辑:程序博客网 时间:2024/06/07 08:43

1、Swift入门学习笔记(第一版),对Swift的基础知识点进行梳理总结。知识点一直在变,只是作为参考,以苹果官方文档为准~

2、在学习完基本的知识点以后会结合官方文档及相关资料,在此版本的基础上进行添加更改。


十一、属性


1、存储属性

存储在特定类或结构体的实例里地一个变量或常量

struct Rectangle {    var length:Int    let width:Int}var rectangleA = Rectangle(length: 2, width: 18)rectangleA.length = 3       //可修改,但是width不可修改//let rectangleB = Rectangle(length: 19, width: 2)//rectangleB.length = 2   //虽然结构体中length是变量属性,但是此处结构体的实例赋值给一个常量,则无法修改该实例的任何属性

原因:
结构体是值类型,值类型的实例被声明为常量时,其所有的属性也就变成了常量

区别于引用类型的类,把一个引用类型的实例赋给一个常量后,仍然可以修改该实例的变量属性


2、延迟存储属性

指当第一次被调用的时候才会计算其初始值的属性。


2.1、说明

lazy关键字声明,但是必须是变量,因为变量属性的初始值可以再实例构造完成之后才会得到。

常量不可以,因为常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。


2.2、使用场景

a、属性的值依赖于在实例构造过程后才会知道具体值

b、获得属性的初始值需要复杂或大量计算时


2.3、注意点

标记为lazy属性在没有初始化时就同时被多个线程访问,则无法保证该属性只会被初始化一次


3、计算属性

不直接存储值,提供一个getter和一个可选的setter,来间接获取和设置其他属性或变量的值

必须使用var关键字定义计算属性,包括只读计算属性,因为他们的值不是固定的


3.1、实例:一矩形长度固定,宽可变

struct Rectangle {    let length:Double = 10.0    var width :Double    var square:Double {        get {            return length * width        }        set(newSquare) {            width = newSquare/length        }        //便捷的setter声明,没有定义新值得参数名,使用默认名称newValue//        set {//            width = newValue/length//        }    }}var rectangle = Rectangle(width: 2.0)print("rectangle Square:\(rectangle.square),length:\(rectangle.length),width:\(rectangle.width)")rectangle.square = 100.0//设置属性square会调用square的setter方法来修改width属性print("rectangle Square:\(rectangle.square),length:\(rectangle.length),width:\(rectangle.width)")

Output:

rectangle Square:20.0,length:10.0,width:2.0rectangle Square:100.0,length:10.0,width:10.0

3.2、便捷setter声明

与上面同,只是如果setter没有定义新值得参数名,那么可以使用默认名称newValue

在前面的代码中的setter备注部分


3.3、只读计算属性

只有getter没有setter的计算属性为计算属性,虽然只读但是仍要用var关键字,因为值不固定

get关键字和setter部分全部去除


4、属性观察器

a、监控和相应属性值的变化,属性被设置都会调用,包括新值和旧值相同的情况

b、可以为延迟属性外的其他存储属性添加属性观察器,也可以通过重写属性的方式为继承的属性(包括存储属性和计算属性)添加属性观察器。(不需要为非重写的计算属性添加属性观察器,其可通过setter方法直接监控和响应变化)

c、为属性添加如下一个或全部观察器
willSet:新值被设置之前调用,指定新的常量名称传入新的属性值,不指定默认
didSet:被设置之后立即调用,指定新的参数名称传入旧的属性值,不指定默认oldValue

d、父类属性在子类的构造器中被赋值时,父类中的willSetdidSet观察器会被调用

e、如果在一个属性的didSet观察器里为它赋值,这个值会替换之前的值

class Figure {    var weight:Double = 0.0{        willSet(newWeight) {            print("Weight:\(newWeight)")        }        didSet {            if weight > oldValue {                print("Amazing!You are fatter!")            }else if weight == oldValue {                print("Oh~There is nothing chang.")            }else {                weight = 0                print("So sad!You get thinner!T^T")            }        }    }}let myFigure = Figure()myFigure.weight = 55.0myFigure.weight = 60.2myFigure.weight = 58.8print(myFigure.weight)      //结果是0,因为变瘦后,我属性里设置值为0(验证点e)

Output:

Weight:55.0Amazing!You are fatter!Weight:60.2Amazing!You are fatter!Weight:58.8So sad!You get thinner!T^T0.0

5、全局变量和局部变量

a、全局变量和局部变量可以使用计算属性和属性观察器

b、全局变量或常量都是延迟计算的,跟延迟存储属性相似,不同的是全局变量或常量不需要标记lazy特性

c、局部范围的常量或变量不会延迟计算


6、类型属性

类型属性是类型本身特有,不管有多少实例,这些属性都只有唯一一份。用于定义特定类型所有实例共享的数据

必须指定默认值,延迟初始化


6.1、语法

类型属性作为类型定义的一部分写在类型最外层的花括号内,其作用范围在类型支持的范围内
使用static定义类型属性。在为类定义计算类型属性时,可以使用关键字class来支持子类对父类的实现

struct TestStruct {    static var string = "structString"    static var value:Int {        return 1    }}enum TestEnum {    static var string = "enumString"    static var value:Int {        return 2    }}class TestClass {    static var string = "classString"    static var value:Int {        return 3    }}//2、获取和设置属性print(TestStruct.string)TestStruct.string = "structStringChanged"print(TestStruct.string)print(TestEnum.value)print(TestClass.value)

Output:

structStringstructStringChanged23
0 0