简介
Swift属性将值与特定的类、结构体或枚举关联。存储属性
会将常量和变量存储为 实例的一部分,而计算属性
则是直接计算(而不是存储)值。计算属性可以用于类、结构体和枚举,而存储属性只能用于类和结构体。
存储属性和计算属性 通常与特定类型的 实例 关联。但是,属性也可以直接与类型本身关联,这种属性称为 类型属性
。
另外,还可以定义属性观察器
来监控属性值的变化,以此来触发自定义的操作。属性观察器可以添加到类本身定义的存储属性上,也可以添加到从父类继承的属性上。
你也可以利用属性包装器来复用多个属性的 getter 和 setter 中的代码。
Swift中,跟实例对象相关的属性,可以分为2大类。
存储属性 & 计算属性
struct Circle {
// 存储属性
var radius: Double
// 计算属性
var diameter: Double {
set {
radius = newValue / 2 // newValue 为传入的新值。
}
get {
return radius * 2
}
}
}
- 存储属性
(Stored Property)
存储在实例对象的内存中。类似于“成员变量”这个概念。
结构体、类可以定义存储属性,枚举不可以。
- 计算属性
(Computed Property)
不占用实例对象的内存。本质就是方法(函数)。
枚举、结构体、类,都可以定义计算属性。
可以理解为OC的“成员属性”,因为手动添加了
get、set
。
存储属性
1、延迟存储属性
关键字lazy
,用来定义一个延迟存储属性。在第一次用到属性时,才会进行初始化。类似懒加载。
class Car {
lazy var count: Int?
lazy var str: String = "天气不错"
}
懒加载的写法
// 格式(一般使用闭包的形式)
lazy var 变量: 类型 = { 创建变量代码 }()
class student: NSObject {
lazy var name: String = {
return "需要时再调用"
}()
lazy var loginBtn : UIButton = {
let btn = UIButton()
btn.backgroundColor = UIColor.red
btn.frame = CGRect(x: 100, y: 100, width: 100, height: 40)
return btn
}()
}
lazy
属性必须声明成var
变量,不能是let
。因为属性的初始值可能在实例构造完成之后才会得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成lazy
。
如果多条线程 同时第一次访问lazy
属性,无法保证只被初始化1次。
2、属性观察器(Property Observer)
监控和响应属性值的变化,每次属性被设置值的时候,都会调用属性观察器,即使新值和当前值相同的时候也不例外。作用类似于OC的KVO。
可以为非lazy
的var
存储属性,设置属性观察器。
-
- 当属性值发生变化时,会调用
willSet、didSet
。
willSet
观察器,会将新的属性值作为常量参数传入,在willSet
的实现代码中可以为这个参数指定一个名称。如果不指定则参数仍然可用,这时使用默认名称newValue
表示。
didSet
观察器,会将旧的属性值作为参数传入,可以为该参数指定一个名称,或者使用默认参数名 oldValue
。如果在 didSet
方法中再次对该属性赋值,那么新值会覆盖旧的值。
注意:在父类初始化方法调用之后,在子类构造器中给父类的属性赋值时,会调用父类属性的
willSet / didSet
观察器。而在父类初始化方法调用之前,给子类的属性赋值时不会调用子类属性的观察器。
对于自定义的计算属性来说,一般使用它的setter
来监控和响应 值的变化,而不是尝试创建 属性观察器。
计算属性
计算属性不直接存储值,而是提供一个 getter
和一个可选的setter
,来间接获取和设置其他属性或变量的值。
定义计算属性只能用var
。因为其值可能发生变化。
struct Circle {
// 存储属性
var radius: Double
// 计算属性
var diameter: Double {
set {
radius = newValue / 2 // newValue 为传入的新值。
}
get {
return radius * 2
}
}
}
- 只读计算属性
只有getter
没有setter
的计算属性。只读计算属性总是返回一个值,可以通过点运算符访问,但不能设置新的值。
只读计算属性的声明可以去掉 get
关键字和花括号:
struct Circle {
// 存储属性
var radius: Double
// 只读 计算属性
var diameter: Double {
return radius * 2
}
}
枚举原始值
rawValue
的本质是 只读计算属性。
类属性(Type Property)
通过关键字static
来定义。
在为类定义计算型类型属性时,可以改用关键字 class
来支持子类对父类的实现进行重写
严格来说,属性可以分为:实例属性、类属性。
struct SomeStructure {
// 存储类属性
static var name = "Tom"
// 计算类属性
static var age: Int {
return 1
}
}
enum SomeEnumeration {
static var name = "Some value."
static var age: Int {
return 6
}
}
class SomeClass {
static var name = "Some value."
//计算类属性
static var age: Int {
return 27
}
// 重写计算类属性
class var overrideableComputedTypeProperty: Int {
return 107
}
}
-
实例属性
(Instance Property)
:
只属于一个类的实例,每创建一个实例,实例都拥有属于自己的一套属性值,实例之间的属性相互独立。只能通过实例对象去访问。
1.存储实例属性
2.计算实例属性 -
类属性
(Type Property)
:
用于定义某个类型 所有实例共享的数据。只能通过类型去访问。
比如所有实例都能用的一个常量(就像 C 语言中的静态常量),或者所有实例都能访问的一个变量(就像 C 语言中的静态变量)。
1.存储类属性:
整个程序运行过程中,只有1份内存(类似全局变量)。
必须设初始值。因为类型本身没有构造器
默认就是lazy,且就算被多个线程同时访问,保证只初始化1次
存储类型属性可以是let
2.计算类属性:
只能定义成var
。
单例
通过 类型属性 + let + private
来写一个单例
public class FileManager {
public static let shared = {
// ....
// ....
return FileManager()
}()
private init() { }
}
网友评论