- 作者: Liwx
- 邮箱: [email protected]
- 源码: 需要
源码
的同学, 可以在评论区
留下您的邮箱
iOS Swift 语法
底层原理
与内存管理
分析 专题:【iOS Swift5语法】00 - 汇编
01 - 基础语法
02 - 流程控制
03 - 函数
04 - 枚举
05 - 可选项
06 - 结构体和类
07 - 闭包
08 - 属性
09 - 方法
10 - 下标
11 - 继承
12 - 初始化器init
13 - 可选项
目录
- 01-继承(Inheritance)
- 02-内存结构
- 03-重写实例方法、下标
- 04-重写类型方法、下标
- 05-重写属性
- 06-重写实例属性
- 07-重写类型属性
- 08-属性观察器(子类为父类存储属性添加属性观察器)
- 09-属性观察器(子类和父类都实现属性观察器)
- 10-属性观察器(子类为父类计算属性添加属性观察器)
- 11-属性观察器(子类为父类类型计算属性添加属性观察器)
- 12-final
01-继承(Inheritance)
-
值类型
(枚举、结构体
)不支持继承, 只有类支持继承
- 没有父类的类,称为:
基类
- Swift并没有像OC、Java那样的规定: 任何类最终都要继承自某个基类
- 子类可以重写父类的
下标、方法、属性
, 重写必须加上override
关键字
02-内存结构
- 类
前16个字节
是用来存放类型信息
和引用计数
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 // 引用计数
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 // 引用计数
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 // 引用计数
0x000000000000000a // 存储属性 age
0x0000000000000014 // 存储属性weight
0x000000000000001e // 存储属性iq
0x0000000000343130 // 未使用
*/
03-重写实例方法、下标
-
重写
实例方法下标override
修饰下标方法subscript
- 调用
父类
的下标方法subscript:super[index]
- 调用
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 // 调用父类下标方法subscript
}
}
anim = Cat() // 多态, 父类指针指向子类对象
anim.speak() // Cat speak
print(anim[6]) // 7
04-重写类型方法、下标
- 被
class
修饰的类型方法、下标,允许
被子类重写 - 被
static
修饰的类型方法、下标,不允许
被子类重写
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修饰下标方法subscript, 报错: Cannot override static subscript
return super[index] + 1
}
}
Cat.speak() // Cat speak
print(Cat[6]) // 7
05-重写属性
- 子类可以将父类的属性(
存储、计算
)重写为计算属性
- 子类
不可以
将父类的属性重写为存储属性
- 只能重写
var
属性, 不能重写let
属性 - 重写时,
属性名、类型要一致
子类重写后的属性权限不能小于
父类属性的权限- 如果父类属性是
只读
的,那么子类重写后的属性可以是只读
的、也可以是可读写
的 - 如果父类属性是
可读写
的,那么子类重写后的属性也必须是可读写
的
- 如果父类属性是
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-属性观察器(子类和父类都实现属性观察器)
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
- 通过汇编观察(子类和父类都实现属性观察器)
// 根据汇编代码分析
set {
call willSet
// 真正设置值
call super set
call didSet
}
10-属性观察器(子类为父类计算属性添加属性观察器)
- 计算属性没占用内存,所以使用
Copy In Copy Out
方式,先调用get方法复制一个副本
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 // 重写计算属性的属性观察器,计算属性原本不占用内存,所以会先调用get方法复制一个副本
// SubCircle willSet 10
// Circle setRadius 10
// Circle getRadius // 此次打印get是因为父类的radius set方法中调用了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是设置之前的值,所以在即将设置之前会调用getRadius来获取设置之前的值
// SubCircle willSet 10
// Circle setRadius 10
// Circle getRadius
// SubCircle didSetRadius 20 20
SubCircle.radius = 10
12-final
- 被
final
修饰的方法、下标、属性
,禁止被重写
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 语法
底层原理
与内存管理
分析 专题:【iOS Swift5语法】下一篇: 12 - 初始化器init
上一篇: 10 - 下标