- 作者: Liwx
- 郵箱: 1032282633@qq.com
- 源碼: 需要
源碼
的同學(xué), 可以在評論區(qū)
留下您的郵箱
iOS Swift 語法
底層原理
與內(nèi)存管理
分析 專題:【iOS Swift5語法】00 - 匯編
01 - 基礎(chǔ)語法
02 - 流程控制
03 - 函數(shù)
04 - 枚舉
05 - 可選項
06 - 結(jié)構(gòu)體和類
07 - 閉包
08 - 屬性
09 - 方法
10 - 下標(biāo)
11 - 繼承
12 - 初始化器init
13 - 可選項
目錄
- 01-繼承(Inheritance)
- 02-內(nèi)存結(jié)構(gòu)
- 03-重寫實例方法、下標(biāo)
- 04-重寫類型方法、下標(biāo)
- 05-重寫屬性
- 06-重寫實例屬性
- 07-重寫類型屬性
- 08-屬性觀察器(子類為父類存儲屬性添加屬性觀察器)
- 09-屬性觀察器(子類和父類都實現(xiàn)屬性觀察器)
- 10-屬性觀察器(子類為父類計算屬性添加屬性觀察器)
- 11-屬性觀察器(子類為父類類型計算屬性添加屬性觀察器)
- 12-final
01-繼承(Inheritance)
-
值類型
(枚舉、結(jié)構(gòu)體
)不支持繼承, 只有類支持繼承
- 沒有父類的類,稱為:
基類
- Swift并沒有像OC、Java那樣的規(guī)定: 任何類最終都要繼承自某個基類
- 子類可以重寫父類的
下標(biāo)、方法、屬性
, 重寫必須加上override
關(guān)鍵字
02-內(nèi)存結(jié)構(gòu)
- 類
前16個字節(jié)
是用來存放類型信息
和引用計數(shù)
class Animal {
var age = 0
}
class Dog : Animal {
var weight = 0
}
class ErHa : Dog {
var iq = 0
}
let a = Animal()
a.age = 10
print(Mems.size(ofRef: a)) // 32
/*
0x00000001000073c8 // 類型信息
0x0000000000000002 // 引用計數(shù)
0x000000000000000a // 存儲屬性 age
0x0000000000000000 // 未使用
*/
print(Mems.memStr(ofRef: a))
let d = Dog()
d.age = 10
d.weight = 20
let dd = d
print(dd)
print(Mems.size(ofRef: d)) // 32
/*
0x0000000100007478 // 類型信息
0x0000000000000002 // 引用計數(shù)
0x000000000000000a // 存儲屬性 age
0x0000000000000014 // 存儲屬性weight
*/
print(Mems.memStr(ofRef: d))
let e = ErHa()
e.age = 10
e.weight = 20
e.iq = 30
print(Mems.size(ofRef: e)) // 48
/*
0x0000000100008548 // 類型信息
0x0000000000000002 // 引用計數(shù)
0x000000000000000a // 存儲屬性 age
0x0000000000000014 // 存儲屬性weight
0x000000000000001e // 存儲屬性iq
0x0000000000343130 // 未使用
*/
03-重寫實例方法、下標(biāo)
-
重寫
實例方法下標(biāo)override
修飾下標(biāo)方法subscript
- 調(diào)用
父類
的下標(biāo)方法subscript:super[index]
- 調(diào)用
class Animal {
func speak() {
print("Animal speak")
}
subscript(index: Int) ->Int {
return index
}
}
var anim: Animal
anim = Animal()
anim.speak() // Animal speak
print(anim[6]) // 6
class Cat : Animal {
override func speak() {
print("Cat speak")
}
override subscript(index: Int) -> Int {
return super[index] + 1 // 調(diào)用父類下標(biāo)方法subscript
}
}
anim = Cat() // 多態(tài), 父類指針指向子類對象
anim.speak() // Cat speak
print(anim[6]) // 7
04-重寫類型方法、下標(biāo)
- 被
class
修飾的類型方法、下標(biāo),允許
被子類重寫 - 被
static
修飾的類型方法、下標(biāo),不允許
被子類重寫
class Animal {
class func speak() {
print("Animal speak")
}
class subscript(index: Int) -> Int {
return index
}
}
Animal.speak() // Animal speak
print(Animal[6]) // 6
class Cat : Animal {
override class func speak() {
print("Cat speak")
}
override class subscript(index: Int) -> Int { // 如果父類用static修飾下標(biāo)方法subscript, 報錯: Cannot override static subscript
return super[index] + 1
}
}
Cat.speak() // Cat speak
print(Cat[6]) // 7
05-重寫屬性
- 子類可以將父類的屬性(
存儲、計算
)重寫為計算屬性
- 子類
不可以
將父類的屬性重寫為存儲屬性
- 只能重寫
var
屬性, 不能重寫let
屬性 - 重寫時,
屬性名、類型要一致
子類重寫后的屬性權(quán)限不能小于
父類屬性的權(quán)限- 如果父類屬性是
只讀
的,那么子類重寫后的屬性可以是只讀
的、也可以是可讀寫
的 - 如果父類屬性是
可讀寫
的,那么子類重寫后的屬性也必須是可讀寫
的
- 如果父類屬性是
06-重寫實例屬性
- 重寫實例屬性, 存儲,計算屬性重寫
class Circle {
var radius: Int = 0
var diameter: Int {
set {
print("Circle setDiameter")
radius = newValue / 2
}
get {
print("Circle getDiameter")
return radius * 2
}
}
}
var circle: Circle
circle = Circle()
circle.radius = 6
// Circle getDiameter
// 12
print(circle.diameter)
// Circle setDiameter
circle.diameter = 20
// 10
print(circle.radius)
class SubCircle : Circle {
override var radius: Int {
set {
print("SubCircle setRadius")
super.radius = newValue
}
get {
print("SubCircle getRadius")
return super.radius
}
}
override var diameter: Int {
set {
print("SubCircle setDiameter")
super.diameter = newValue
}
get {
print("SubCircle getDiameter")
return super.diameter
}
}
}
circle = SubCircle()
// SubCircle setRadius
circle.radius = 6
// SubCircle getDiameter
// Circle getDiameter
// SubCircle getRadius
// 12
print(circle.diameter)
// SubCircle setDiameter
// Circle setDiameter
// SubCircle setRadius
circle.diameter = 20
// SubCircle getRadius
// 10
print(circle.radius)
07-重寫類型屬性
- 被
class
修飾的計算類型屬性
,可以
被子類重寫 - 被
static
修飾的類型屬性(存儲, 計算)
,不可以
被子類重寫
class Circle {
static var radius: Int = 0
class var diameter: Int {
set {
print("Circle setDiameter")
radius = newValue / 2
}
get {
print("Circle getDiameter")
return radius * 2
}
}
}
class SubCircle : Circle {
// override var radius: Int { static修飾的類型屬性不能重寫 // error: property does not override any property from its superclass
// set {
// super.radius = 2
// }
// get {
// return 10
// }
// }
override class var diameter: Int {
set {
print("SubCircle setDiameter")
super.diameter = newValue > 0 ? newValue : 0
}
get {
print("SubCircle getDiameter")
return super.diameter
}
}
}
Circle.radius = 6
// 6
print(Circle.radius)
// Circle getDiameter
Circle.diameter = 20
// 10
print(Circle.radius)
print("----")
SubCircle.radius = 6
// SubCircle getDiameter
// Circle getDiameter
// 12
print(SubCircle.diameter)
// SubCircle setDiameter
// Circle setDiameter
SubCircle.diameter = 20
// 10
print(SubCircle.radius)
08-屬性觀察器(子類為父類存儲屬性添加屬性觀察器)
- 可以在子類中為父類屬性(除了
只讀計算屬性
、let
屬性)增加屬性觀察器
class Circle {
var radius: Int = 1
let count: Int = 1
var diameters: Int { // 只讀計算屬性
radius * 2
}
}
class SubCircle : Circle {
override var radius: Int {
willSet {
print("SubCircle willSetRadius", newValue)
}
didSet {
print("SubCircle didSetRadius", oldValue, radius)
}
}
// // 不能給let屬性重寫屬性觀察器
// override let count: Int { // error: 'let' declarations cannot be observing properties
// willSet {
//
// }
// didSet {
//
// }
// }
// // 不能給只讀計算屬性重寫屬性觀察器
// override var diameters: Int { // error: cannot observe read-only property 'diameters'; it can't change
// willSet {
//
// }
// didSet {
//
// }
// }
}
var circle = SubCircle()
// SubCircle willSetRadius 10
// SubCircle didSetRadius 1 10
circle.radius = 10
09-屬性觀察器(子類和父類都實現(xiàn)屬性觀察器)
class Circle {
var radius: Int = 1 {
willSet {
print("Circle willSetRadius", newValue)
}
didSet {
print("Circle didSetRadius", oldValue, radius)
}
}
}
class SubCircle : Circle {
override var radius: Int {
willSet {
print("SubCircle willSetRadius", newValue)
}
didSet {
print("SubCircle didSetRadius", oldValue, radius)
}
}
}
var circle = SubCircle()
// SubCircle willSetRadius 10
// Circle willSetRadius 10
// Circle didSetRadius 1 10
// SubCircle didSetRadius 1 10
circle.radius = 10
- 通過匯編觀察(子類和父類都實現(xiàn)屬性觀察器)
image.png
// 根據(jù)匯編代碼分析
set {
call willSet
// 真正設(shè)置值
call super set
call didSet
}
10-屬性觀察器(子類為父類計算屬性添加屬性觀察器)
- 計算屬性沒占用內(nèi)存,所以使用
Copy In Copy Out
方式,先調(diào)用get方法復(fù)制一個副本
class Circle {
var radius: Int {
set {
print("Circle setRadius", newValue)
}
get {
print("Circle getRadius")
return 20
}
}
}
class SubCircle : Circle {
override var radius: Int {
willSet {
print("SubCircle willSet", newValue)
}
didSet {
print("SubCircle didSet", oldValue, radius)
}
}
}
var circle = SubCircle()
// Circle getRadius // 重寫計算屬性的屬性觀察器,計算屬性原本不占用內(nèi)存,所以會先調(diào)用get方法復(fù)制一個副本
// SubCircle willSet 10
// Circle setRadius 10
// Circle getRadius // 此次打印get是因為父類的radius set方法中調(diào)用了newValue
// SubCircle didSet 20 20
circle.radius = 10
11-屬性觀察器(子類為父類類型計算屬性添加屬性觀察器)
-
Xcode 11.4.1
以下代碼報錯
, 不知什么原因!待排查
class Circle {
class var radius: Int {
set {
print("Circle setRadius", newValue)
}
get {
print("Circle getRadius")
return 20
}
}
}
class SubCircle : Circle {
override static var radius: Int {
willSet {
print("SubCircle willSet", newValue)
}
didSet {
print("SubCircle didSet", oldValue, radius)
}
}
}
// Circle getRadius // oldValue是設(shè)置之前的值,所以在即將設(shè)置之前會調(diào)用getRadius來獲取設(shè)置之前的值
// SubCircle willSet 10
// Circle setRadius 10
// Circle getRadius
// SubCircle didSetRadius 20 20
SubCircle.radius = 10
12-final
- 被
final
修飾的方法、下標(biāo)、屬性
,禁止被重寫
class Circle {
final func test() {
print("Circle test")
}
}
class SubCircle : Circle {
// 不能重寫final修飾的方法
override final func test() { // error: instance method overrides a 'final' instance method
}
}
- 被
final
修飾的類
,禁止被繼承
final class Circle {
var radius: Int = 0
}
// 不能繼承final修飾的類
class SubCircle : Circle { // error: inheritance from a final class 'Circle'
}
iOS Swift 語法
底層原理
與內(nèi)存管理
分析 專題:【iOS Swift5語法】下一篇: 12 - 初始化器init
上一篇: 10 - 下標(biāo)