目录
实例说明
func instanceExplain(){
//枚举
enum Season{
case spring,summer,autumn,winter
}
let s = Season.spring
//结构体
struct Point{
var x:Int = 0
var y:Int = 0
}
let p = Point()
//类
class Size{
var width = 0
var height = 0
}
let si = Size()
// s p si就是实例
print(s,p,si,separator:"\n")
}
存储属性
func storedPropertyExplain(){
/**
Swift中跟实例相关的属性可以分为2大类:存储属性、计算属性
存储属性(Stored Property)
类似于成员变量这个概念
存储在实例的内存中
结构体、类可以定义存储属性
枚举不可以定义存储属性
关于存储属性,Swift有个明确的规定
在创建类 或 结构体的实例时,必须为所有的存储属性设置一个合适的初始值
可以在初始化器里为存储属性设置一个初始值
可以分配一个默认的属性值作为属性定义的一部分
*/
//1、结构体的存储属性
do{
struct Point{
var x:Int = 0//存储属性 类似于成员变量 存储在实例的内存中
var y:Int = 0//存储属性 类似于成员变量 存储在实例的内存中
}
var p = Point()
p.x = 10
p.y = 10
print(p)//Point(x: 10, y: 10)
}
//2、类的存储属性
do{
class Size{
var width:Int = 0//存储属性 类似于成员变量 存储在实例的内存中
var height:Int = 0//存储属性 类似于成员变量 存储在实例的内存中
}
let s = Size()
s.width = 80
s.height = 180
print(s.width,s.height)//80 180
}
//3、枚举没有存储属性
do{
//实例占用1个字节 侧面证明没有存储属性 内存中没有放置存储属性的空间
enum Season{
//var stored:Int//报错 Enums must not contain stored properties
case spring,summer,autumn,winner
}
//实例占用16个字节 侧面证明没有存储属性 内存中没有放置存储属性的空间
enum Date{
//var stored:Int////报错 Enums must not contain stored properties
case day(Int)
case month(Int)
case year(Int)
}
print("DateSize = ",MemoryLayout<Date>.size);//9
print("DateStride = ",MemoryLayout<Date>.stride);//16
print("DateAlignment = ",MemoryLayout<Date>.alignment);//8
}
}
计算属性
func computedPropertyExplain(){
/**
计算属性(Computed Property)
本质就是方法(函数)
不占用实例的内存
枚举、结构体、类都可以定义计算属性
计算属性必须用var修饰,不能用let,
let代表常量:值是一成不变的,
计算属性的值是可能发生变化的(即使是只读计算属性)
*/
//1、结构体的计算属性
struct Circle{
//半径 存储属性
var radius:Int = 0
//计算属性 本质是方法 不占用实例的内存 定义计算属性必须用var 不能使用let
var diameter:Int{
set(nValue){
radius = nValue / 2
}
get{
return radius * 2
}
}
//也简写成这种格式
var diameter2:Int{
set{
//set 传入的新值默认叫做newValue 也可以自定义
radius = newValue/2
}
get{
radius*2
}
}
//只读计算属性:只有get 没有set
var diameter3:Int{
get{
radius*2
}
}
//只读计算属性:可以简写
var diameter4:Int{ radius*2 }
//只有set 会报错 Variable with a setter must also have a gette
// var diameter5:Int{
// set{
// radius = newValue / 2
// }
// }
}
//创建并初始化一个实例
var c = Circle(radius: 10)
/**
-> 0x1000172e3 <+211>: callq 0x100017950
; diameter.setter : Swift.Int in Circle #1 in LCClientDemo_commond.computedPropertyExplain() -> () at 8-01-属性、汇编分析inout本质.swift:115
c.diameter= 本质是方法调用 setter
*/
c.diameter = 30//15 30
/**
-> 0x100017310 <+256>: callq 0x100017900
; diameter.getter : Swift.Int in Circle #1 in LCClientDemo_commond.computedPropertyExplain() -> () at 8-01-属性、汇编分析inout本质.swift:118
=c.diameter本质是方法调用 getter
*/
print(c.radius,c.diameter)
}
rawValue的本质是
func enumRawValueExplain(){
enum Season:Int{
case spring = 1,summer,autumn,winter
//enum 的 rawValue的本质是计算属性
var rawValue: Int{
get{
switch self {
case .spring:
return 10
case .summer:
return 20
case .autumn:
return 30
case .winter:
return 40
}
}
}
}
/**
-> 0x10001798a <+10>: callq 0x1000181f0
; rawValue.getter : Swift.Int in Season #1 in LCClientDemo_commond.enumRawValueExplain() -> () at <compiler-generated>
*/
let value = Season.spring.rawValue
print(value)
}
延迟存储属性
func lazyStoredProperty() -> Void {
//使用lazy可以定义一个延迟存储属性,在第一次用到属性的时候才会进行初始化
//1、lazy使用
do{
class Car{
init() {
print("Car init!")
}
func run() -> Void {
print("Car is running !")
}
}
class Person{
lazy var car = Car()
// var car = Car()
init() {
print("Person init !")
}
func goOut() -> Void {
car.run()
}
}
let p = Person()
p.goOut()
//没有lazy 修饰的情况
/**
Car init!
Person init !
Car is running !
*/
//有lazy修饰的情况
/**
Person init !
Car init!
Car is running !
*/
}
//2、lazy使用
do{
struct Point{
var x = 0
var y = 0
lazy var z = 0
}
/**
有lazy修饰 实例使用let 时 存储属性会进行取值赋值操作时会报错
Cannot use mutating getter on immutable value: 'po' is a 'let' constant
*/
//let po = Point()
/**
当结构体包含一个延迟存储属性时,只有var才能访问延迟存储属性
因为延迟存储属性初始化时需要改变结构体的内存
*/
var po = Point()
let z = po.z
print(z)
}
//3、总结
/**
lazy 属性必须var 不能是let
let 必须在实例的初始化方法完成之前就拥有值
当结构体包含一个延迟存储属性时,只有var才能访问延迟存储属性
因为延迟存储属性初始化时需要改变结构体的内存
多线程同时第一次访问lazy属性无法保证属性只被初始化一次
*/
}
属性观察器
func propertyObserver() -> Void {
/**
可以为非lazy的var存储属性设置属性观察器
willSet会传递新值,默认叫newValue
didSet会传递旧值,默认叫oldValue
在初始化器中设置属性值不会触发willSet和didSet
在属性定义时设置初始值也不会触发willSet和didSet
*/
//1、属性观察器
do{
print("---------1----------")
struct Circle{
//必须是var修饰的存储属性才有 willSet 和 didSet
var radius:Int{
willSet{
print("willSet",newValue)
}
didSet{
print("didSet",oldValue,radius)
}
}
init() {
//初始化器中不会触发willSet 和 didSet
self.radius = 1
print("circle init")
}
}
//circle init
var r = Circle()
//willSet 20
//didSet 1 20
r.radius = 20
}
//2、局部变量也有属性观察器 和 计算属性
do{
print("---------2----------")
//属性观察器
var a = 10{
willSet{
print("willSet",newValue)
}
didSet{
print("didSet",oldValue,a)
}
}
a = 100
//计算属性
var b:Int{
set{
print("b",newValue)
}
get{
return 10
}
}
//b 20
b = 20
print(b)//10
}
//3、全局变量也有属性观察器 和 计算属性
}
行者常至,为者常成!