继承(Inheritance)
值类型(枚举、结构体)不支持继承, 只有引用类型(类)才支持继承.
没有父类的类,称为基类(Swift其实有一个隐藏的基类:_SwiftObject
)。 Swift并没有像OC、Java那样的规定: 任何类最终都要继承自某个基类。
子类可以重写父类的下标、方法、属性, 重写必须加上override
关键字。
内存结构
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
/* 0x0000000100009a30 // 指向类型信息的指针
0x0000000000000002 // 存储引用计数相关信息
0x000000000000000a // 存储属性age的值
0x00027fff729cb010 // 未使用,iOS或者Mac堆内存分配是16的倍数, 这是附带的。
*/
print(Mems.memStr(ofRef: a)) // 获取a指向内存空间的值
let d = Dog()
d.age = 10
d.weight = 20
print(Mems.size(ofRef: d)) // 系统分配的内存: 32
/*
0x0000000100009ae0 // 指向类型信息的指针
0x0000000000000002 // 存储引用计数相关信息
0x000000000000000a // 存储属性age的值
0x0000000000000014 // 存储属性weight的值
*/
print(Mems.memStr(ofRef: d)) // 获取d指向内存空间的值
let e = ErHa()
e.age = 10
e.weight = 20
e.iq = 30
print(Mems.size(ofRef: e)) // 系统分配的内存: 48
/*
0x0000000100009bb0 // 指向类型信息的指针
0x0000000000000002 // 存储引用计数相关信息
0x000000000000000a // 存储属性age的值
0x0000000000000014 // 存储属性weight的值
0x000000000000001e // 存储属性iq的值
0x0003000000000000 // 未使用,iOS或者Mac堆内存分配是16的倍数, 这是附带的。
*/
print(Mems.memStr(ofRef: e)) // 获取e指向内存空间的值
重写实例方法和下标
class Animal {
func speak() {
print("Animal speak")
}
subscript(index: Int) -> Int {
return index
}
}
class Cat: Animal {
override func speak() { // 重写必须加上override 关键字
super.speak()
print("Cat speak")
}
override subscript(index: Int) -> Int { // 重写必须加上override 关键字
return super[index] + 1
}
}
var anim: Animal
anim = Animal()
anim.speak() // Animal speak
print(anim[6]) // 6
var cat = Cat()
//Animal speak
//Cat speak
cat.speak()
// 7
print(cat[6])
重写类型方法和下标
被class
修饰的类型方法、下标, 允许被子类重写。
被static
修饰的类型方法、 下标, 不允许被子类重写。
class Animal {
class func speak() {
print("Animal speak")
}
class subscript(index: Int) -> Int {
return index
}
}
class Cat: Animal {
override class func speak() { // 重写必须加上override 关键字
super.speak()
print("Cat speak")
}
override class subscript(index: Int) -> Int { // 重写必须加上override 关键字
return super[index] + 1
}
}
// Animal speak
Animal.speak()
// 6
print(Animal[6])
//Animal speak
//Cat speak
Cat.speak()
print(Cat[6]) //7
重写实例属性
- 子类可以将父类的属性(存储,计算)重写为计算属性
- 子类不可以将父类属性重写为存储属性。
- 只能重写
var
属性,不能重写let
属性 - 重写时,属性名,类型要一致。
- 子类重写后的属性权限不能小于父类的属性权限。
- 如果父类的属性是只读的,那么子类重写后的属性可以是只读,也可以是可读写的。
- 如果父类属性是可读写的, 那么子类重写后的属性必须也是可读写的。
class Circle {
var radius: Int = 0
var diameter: Int {
set {
print("Circle setDiameter")
radius = newValue / 2
}
get {
print("Circle getDiameter")
return radius * 2
}
}
}
class SubCircle: Circle {
override var radius: Int {
set {
print("SubCircle setRadius")
super.radius = newValue > 0 ? newValue : 0;
}
get {
print("SubCircle getRadius")
return super.radius
}
}
override var diameter: Int {
set {
print("SubCircle setDiameter")
super.diameter = newValue > 0 ? newValue : 0
}
get {
print("SubCircle getDiameter")
return super.diameter
}
}
}
var circle = SubCircle()
circle.radius = 6 // "SubCircle setRadius
print(circle.diameter) // SubCircle getDiameter" -> "Circle getDiameter" -> SubCircle getRadius
circle.diameter = 20 // "SubCircle setDiameter" -> Circle setDiameter -> SubCircle setRadius
print(circle.radius) // SubCircle getRadius
重写类型属性
- 被
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 static var diameter: Int {
set {
print("SubCircle setDiameter")
super.diameter = newValue > 0 ? newValue : 0
}
get {
print("SubCircle getDiameter")
return super.diameter
}
}
}
属性观察器
可以在子类中为父类属性(除了只读计算属性、let属性)增加属性观察器
class Circle {
var radius: Int = 1
}
class SubCircle: Circle {
override var radius: Int {
willSet {
print("SubCircle willSetRadius", newValue)
}
didSet {
print("SubCircle didSetRadius", oldValue, radius)
}
}
}
var circle = SubCircle()
circle.radius = 20
打印:
SubCircle willSetRadius 20
SubCircle didSetRadius 1 20
就算父类也存在属性观察器,子类也是可以重写的。
class Circle {
var radius: Int = 1 {
willSet {
print("Circle willSetRadius")
}
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()
circle.radius = 20
如果父类是一个计算属性
class Circle {
var radius: Int {
set {
print("Circle set Radius", newValue)
}
get {
print("Circle get Radius")
return 20
}
}
}
class SubCircle: Circle {
override var radius: Int {
willSet {
print("SubCircle willSetRadius", newValue)
}
didSet {
print("SubCircle didSetRadius", oldValue, radius)
}
}
}
var circle = SubCircle()
circle.radius = 20
打印如下:
Circle get Radius // 这一行打印是为了保留oldValue
SubCircle willSetRadius 20
Circle set Radius 20
Circle get Radius
SubCircle didSetRadius 20 20
Program ended with exit code: 0
父类属性使用class
修饰, 子类可以使用static
进行重写:
class Circle {
class var radius: Int {
set {
print("Circle set Radius", newValue)
}
get {
print("Circle get Radius")
return 20
}
}
}
class SubCircle: Circle {
override static var radius: Int {
willSet {
print("SubCircle willSetRadius", newValue)
}
didSet {
print("SubCircle didSetRadius", oldValue, radius)
}
}
}
final
被final
修饰的方法、下标、属性、禁止被重写
被final
修饰的类, 禁止被继承。