// 值类型(枚举、结构体)不支持继承,只有类才支持继承
// swift中不想OC、Java中必须继承至某个父类,默认就是基类
// 子类可重写父类的下标、方法、属性,重写必须加上override关键字
// 1.内存结构
func test_memory() {
class Animal {
var age = 5
// 打印Animal实例可知,该类占用24个字节
// 事实上通过详细分析原理得知,该类的实例内存分为三块
/** Animal 实例 内存结构
占用3*8=24个字节,由于ios系统分配是以16倍数分配,故分配32个字节
┏━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━━━┓
┃ classInfo ┃ ┃ 0x0000000100078e ┃
┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛
┃ retainCount ┃ ┃ 0x00000000000001 ┃
┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛
┃ var age ┃ ┃ 0x00000000000005 ┃
┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛
*/
}
class Dog: Animal {
var weight = 7
/** Dog 实例 内存结构
占用4*8=32个字节,由于ios系统分配是以16倍数分配,故任然分配32个字节
┏━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━━━┓
┃ classInfo ┃ ┃ 0x0000000100078e ┃
┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛
┃ retainCount ┃ ┃ 0x00000000000001 ┃
┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛
┃ var age ┃ ┃ 0x00000000000005 ┃
┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛
┃ var weight ┃ ┃ 0x00000000000007 ┃
┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛
*/
}
class WhiteDog: Dog {
var height = 15
/** Dog 实例 内存结构
占用4*8=40个字节,由于ios系统分配是以16倍数分配,故分配48个字节
┏━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━━━┓
┃ classInfo ┃ ┃ 0x0000000100078e ┃
┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛
┃ retainCount ┃ ┃ 0x00000000000001 ┃
┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛
┃ var age ┃ ┃ 0x00000000000005 ┃
┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛
┃ var weight ┃ ┃ 0x00000000000007 ┃
┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛
┃ var height ┃ ┃ 0x0000000000000f ┃
┗━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛
*/
}
// 综上
// swift中的集成结构实际操作为,将父类的存储属性拷贝到子类当中(这里点类似C++)
// classInfo部分实际上是虚表地址(方法列表)
// retainCount是引用计数器
}
test_memory()
// 2.重写下标、方法
func test_override_method_subscript() {
class Animal {
func speak() {
print("Animal obj speak")
}
class func speak() {
print("Animal speak")
}
subscript(index: Int)->Int { 10 }
}
class Dog: Animal {
override func speak() {
super.speak()
print("Dog obj speak")
}
override class func speak() {
super.speak()
print("Dog speak")
}
override subscript(index: Int) -> Int { super[index] + 20 }
}
print("类方法重写-------")
Animal.speak()
Dog.speak()
print("实例方法重写-------")
let a = Animal()
let d = Dog()
a.speak()
d.speak()
print("下标方法重写-------")
print("---->\(a[0])")
print("---->\(d[0])")
}
test_override_method_subscript()
// 3.重写实例属性
// 无论父类是存储类型还是计算类型,在子类中重写都职能重写为计算类型
// 如果是类属性
// calss修饰的计算属性可以被子类重写(class只能在类中声名计算属性)
// static修饰的存储和计算属性都不可以被子类重写
//
// 注意:我们都知道,属性观察期和计算属性不能共存(set、get与willSet、didSet)
// 但是可以将父类中的计算属性,在子类中重写添加观察器,也可以重写观察器
func test_override_property() {
class A {
var x: Int = 10
var y: Int {
set { x = newValue / 2 }
get { x * 2 }
}
static var z = 10
class var z1: Int {
set { }
get { 10 }
}
var f: Int = 10
var f1: Int {
set { }
get { 10 }
}
var f2: Int = 10 {
willSet {}
didSet {}
}
}
class SubA: A {
override var x: Int {
set { super.x = newValue > 0 ? newValue : 0 }
get { super.x }
}
override var y: Int {
set { super.y = newValue / 3 }
get { super.y * 3 }
}
override var f: Int {
willSet {}
didSet {}
}
override var f1: Int {
willSet {}
didSet {}
}
override var f2: Int {
willSet {}
didSet {}
}
}
// 重写子类观察器,父类观察器也会被调用
class B {
class var x: Int {
set { print("B set") }
get { print("B get"); return 10}
}
}
class SubB: B {
override class var x: Int {
willSet { print("B willSet \(newValue)") }
didSet { print("B didSet \(oldValue), \(x)") }
}
}
SubB.x = 30
/**
B get
SubB willSet 30
B set
B get
SubB didSet 10, 10
// 后边4个步骤容易理解,主要是第一步,原因是需要先获取到x变量的地址,所以预先getter
*/
}
test_override_property()
// final
func test_final() {
// 被final修饰的类、方法、下标、属性,禁止被重写
/** 类
final class A {}
class SubA : A {}
*/
class A {
final var x: Int = 10
final var y: Int {
set {}
get {10}
}
final class var z: Int {
set {}
get {10}
}
}
class SubA : A {
// 都不能重写
}
}
test_final()
网友评论