Swift5.1-继承

82 阅读5分钟

继承(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

重写实例属性

  1. 子类可以将父类的属性(存储,计算)重写为计算属性
  2. 子类不可以将父类属性重写为存储属性。
  3. 只能重写var属性,不能重写let属性
  4. 重写时,属性名,类型要一致。
  5. 子类重写后的属性权限不能小于父类的属性权限。
    • 如果父类的属性是只读的,那么子类重写后的属性可以是只读,也可以是可读写的。
    • 如果父类属性是可读写的, 那么子类重写后的属性必须也是可读写的。
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修饰的类, 禁止被继承。