属性:存储于类,结构体的内存空间中
struct Point { var x :Int var diameter:Double{ set { x = newValue/2 } get { x*2 } }
} var p = Point() 枚举只存储关联值的内容
计算属性 本质就是方法(函数) 相当于内部定义了一个 fun setDiameter(newValue: Double) func getDiameter() 存储于内部的数据中 不占用实例的内存 调用diameter的方法,就是正常的调用set方法 枚举,结构体,类都可以存储计算属性
在创建类或者属性的关联值的时候,保证存储属性的初始化 enum 中的rawValue是实现的计算属性,不占有存储空间,只读的计算属性 只有getter方法
属性观察器 可以为非lazy 的var 存储属性设置属性观察器
struct Circle { var radius:Double { willSet{
}
didSet {
}
}
}
在初始化中,去设置内容,是不会触发属性观察器的 func test(_ num: inout Int ) { num = 20 } // 引用传递的类型,输入输出参数类型, 实际上是传递的对应的地址值,然后进行修改 //但是是如何修改计算属性的内容? 实际上调用了计算属性的getter 和 setter的方法
先调用计算属性的getter方法,计算出一个临时的值 然后把临时的值的地址,传递给函数,函数进行处理 函数的inout方法,传递结果给计算属性的setter方法
如果带有属性观察器的,是需要先拿到一个值,然后赋值给一个局部变量 然后将局部变量的值,替换给test的方法 使用局部变量 相当于就是s.side = 20 这样再次触发 产生一个副本
内存的修改是,当修复完毕之后,再重新赋值给test 的 能做的就是willset和didset方法进行处理的
inout的本质总结 如果实参有物理内存地址,且没有设置存储属性观察器 直接将实参的内存地址传入函数
如果实参是计算属性,或者设置了属性观察器 采用copy in copy out 的做法 1:调用函数时候,先复制实参的值,产生副本【get】 2:将副本的内存地址传入函数(副本进行引用传递,)在函数内部可以修改副本的值 3:函数返回后,再将副本的值覆盖实参的值【set 】
inout的本质总结 就是引用传递(地址传递)
类型属性 严格说来,属性分为 1:实例属性,只能通过实例去访问 2:存储实例属性: 3:计算实例属性
类型属性: 存储类型属性,整个程序运行过程中,只能存储一份内存(类似全局属性) struct Shape { var width:Int = 0 static var count:Int = 0 } //访问的类型属性 Shape.count = 10
count 相当于全局变量 swift_once 调用 了dispatch_once