一.private与fileprivate 修饰的函数,编译器会进行检查如果没有继承,编译器默认就添加final标识
二.存储属性
- 存储属性作为一个特定类和结构体实例一部分的常量或者变量,存储属性要们是变量存储属性(由var关键字引入)要么是常量存储属性(由let关键字引入)
- let用来声明常量,常量的值一旦设置好便不能再被修改,var用来声明变量,变量的值可以将来设置不同的值
- 在sil文件中得到,编译器会对var修饰的变量会生成{get,set}方法,let修饰的变量只会生成{get}方法,找不到set方法,所以用let修饰的变量是不能修改的
三.计算属性
- 存储的属性是常见的,除了存储属性,类,结构体和枚举也能够定义计算属性,计算属性并不存储值,他们提供getter和setter来修改和获取值,对于存储属性来说可以是常量或变量,但是计算属性必须是变量,与此同时我们书写计算属性时候必须包含类型,因为编译器需要期望返回值是什么
struct squqre{
var width: Doule
var height: Double
//struct是静态派发
//本质上是方法,但是不存储方法,不占据内存空间
var area: Doble{
get{
return width * height//return 可以省略,编译器能推断出
}
set{
//newValue是编译器默认帮忙生成的*
self.width = newValue
}
}
private(set) var age:Double//对当前结构体来访问是可行的,外部不能访问
fun test(){
self.age = 1.0
}
//计算属性的本质就是set和get方法
}
四.属性观察者
- 属性观察者会观察属性值的变化,一个willSet当属性将要被改变时调用,即使这个值与原有的值相同,而didSet在属性已经改变后调用,它们的语法类似getter和setter
class SubjectName{
//存储属性
var subjectName: String = ""{
willSet{
print("subjectName will set value\(newValue)")
}
didSet{
print("subjectName has been changed\(newValue))
}
}
}
let s = SubjectName()
s.subjectName = "changeName"
- 生成sil文件知道,在底层赋值的时候会调用willSet,赋值完成后会调用didSet,但是在第一次初始化的时候是不会调用这两个方法的,在初始化的时候是值的拷贝,当然在初始化过程中也不应该调用willSet和didSet,是不安全的
//在继承当中,
class Teacher{
var age:Int
var height:Double
init(_ age: Int, _ height: Double){
willSet{
//2
}
didSet{
//3
}
}
}
class Son:Teacher{
override var age:Int{
willSet{
//1
}
didSet{
//4
}
}
init(){
super.init(18,19)
//初始化已经完成
self.age = 20
}
}
//调用顺序如上1->2->3->4
五.类型属性
class Subject{
//全局静态变量只会被初始化一次,底层是用的dispatch_once_t
static var age: Int = 18
}
class Subject{
//单利的创建
static let shareInstance = Subject()
private init(){}
}
class Subject{
//单利的创建
static fun test(){
let x = 20
let y = 30
var tmp = x + y
print(tmp)
}
//在这个静态函调用过程中就不会涉及到函数派发
}
六.属性在mahco文件的位置信息
struct Metadata{
var kind:Int
var superClass:any.Type
var cacheData:(Int,Int)
...
var typeDescriptor:UnsafeMutableRawPointer
var iVarDestroyer:UnsafeRawPoniter
...
}
在函数调度过程中,我们知道了我们的函数表存储在typeDescriptor
struct TargetClassDescriptor{
...
var fieldDescriptor:Int32//存储的属性
...
}
struct FieldDescriptor{
MangledTypeName int32
Superclass int32
...
NumFields uint32//代表有多少个属性
FieldRecords [FieldRecord]//记录相关的属性
}
struct FieldRecord{
Flags uint32
MangledTypeName int32
fieldName int32//属性名称
}
通过macho-view可以通过相关偏移查到属性的值