美文网首页Swift
Swift基础语法(八)继承

Swift基础语法(八)继承

作者: iOS之文一 | 来源:发表于2022-05-14 19:17 被阅读0次

    Swift基础语法文章汇总

    Swift的继承与其他语言并无两样,本文主要把重写进行了说明,主要是方法/下标重写、属性重写、属性观察器重写,其实他们的本质也就是方法重写。

    主要内容:

    1. 方法/下标重写
    2. 属性重写
    3. 属性观察器重写

    1、继承认识

    继承概念没区别,都是父类子类的关系,也没必要赘言了
    这里只看下内存结构

    代码:

    /*
     1、内存结构
     */
    func test1() {
        class Animal {
            var age = 0
        }
        class Dog : Animal {
            var weight = 0
        }
        class ErHa : Dog {
            var iq = 0
        }
        
        //父类
        let a = Animal()
        a.age = 10
        // 32
        print(Mems.size(ofRef: a))
        /*
         0x00000001000073e0
         0x0000000000000002
         0x000000000000000a
         0x0000000000000000
         */
        print(Mems.memStr(ofRef: a))
        
        //子类
        let d = Dog()
        d.age = 10
        d.weight = 20
        // 32
        print(Mems.size(ofRef: d))
        /*
         0x0000000100007490
         0x0000000000000002
         0x000000000000000a
         0x0000000000000014
         */
        print(Mems.memStr(ofRef: d))
        
        //孙子类
        let e = ErHa()
        e.age = 10
        e.weight = 20
        e.iq = 30
        // 48
        print(Mems.size(ofRef: e))
        /*
         0x0000000100007560
         0x0000000000000002
         0x000000000000000a
         0x0000000000000014
         0x000000000000001e
         0x0000000000000000
         */
        print(Mems.memStr(ofRef: e))
        
    }
    test1()
    

    说明:

    1. 父类继承过来的存储属性是放在前面的
    2. 子类继承父类的存储属性是拷贝到子类中的

    2、重写

    子类可以重写父类的属性、下标、方法,重写必须加上override关键字(required不需要),需要注意的是不管是方法、下标、属性、属性观察器,所有的重写本质都是函数重写

    2.1 方法/下标

    下标其实就是方法,所以放到一起写

    2.1.1 实例方法

    代码:

    /*
     2、下标、方法重写
     */
    func test2() {
        class Animal {
            func speak() {
                print("Animal speak")
            }
            subscript(index: Int) -> Int {
                return index
            }
        }
        
        class Cat : Animal {
            //方法重写
            override func speak() {
                super.speak()
                print("Cat speak")
            }
            //下标重写
            override subscript(index: Int) -> Int {
                return super[index] + 1
            }
        }
        
        let cat: Animal = Cat()
        cat.speak()
        print(cat[1])
    }
    test2()
    

    说明:

    • 下标和方法只要在前边加上override就声明被重写了

    2.1.2 类型方法

    代码:

    /*
     2、下标、方法重写
     */
    func test2() {
        class Animal {
            class func speak() {
                print("Animal speak")
            }
            class subscript(index: Int) -> Int {
                return index
            }
        }
        
        class Cat : Animal {
            //方法重写
            override class  func speak() {
                super.speak()
                print("Cat speak")
            }
            //下标重写
            override class  subscript(index: Int) -> Int {
                return super[index] + 1
            }
        }
        Cat.speak()
        print(Cat(2))
    }
    test2()
    

    说明:

    • 类型方法也是一样,只是在调用时需要通过类型调用
    • 被class修饰的类型方法、下标,允许被子类重写
    • 被static修饰的类型方法、下标,不允许被子类重写
    • 注意重写的方法/下标可以是static

    2.2 属性

    属性本身是没有重写的,只有继承,但是在Swift中有计算属性和属性观察器这两种东西,他们本质上也是函数,所以这两种也可以重写

    属性重写的种类:

    1. 计算属性重写为计算属性;
    2. 存储属性重写为计算属性;
    3. 存储属性重写成带有属性观察器的存储属性

    代码:

    /*
     3、属性重写
     */
    func test3() {
        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
                }
            }
        }
        let circle = SubCircle()
        
        //SubCircle setradius
        circle.radius = 6
        
        /*
         SubCircle getDiameter
         Circle getDiameter
         SubCircle getradius
         12
         */
        print(circle.diameter)
        
        //SubCircle setDiameter
        circle.diameter = 20
        
        /*
         SubCircle setDiameter
         Circle setDiameter
         SubCircle setradius
         SubCircle getradius
         10
         */
        print(circle.radius)
    }
    test3()
    

    说明:

    1. 仅仅只是普通的重写,没什么特殊的
    2. 只是需要注意在调用circle.diameter时,调用一下父类的getDiameter方法,因为在子类的getDiameter方法中会调用super的diameter

    注意:

    • 子类可以将存储属性和计算属性重写为计算属性
    • 子类不可以将父类属性重写成存储属性
      • 存储属性只能继承
      • 但是如果子类增加属性观察器,也就可以重写
      • 子类不能将父类的存储属性重写为存储属性,因为子类本身就会有父类的存储属性,所以没必要重写
    • 只能重写var属性,不能重写let属性,这个很正常,重写就是为了子类修改实现
    • 重写时,属性名、类型要一致
    • 子类重写后的属性权限不能小于父类属性的权限
    • 被Class修饰的计算类型属性,可以被子类重写
    • 被static修饰的类型属性(存储、计算),不可以被子类重写

    2.3 属性观察器

    可以在子类中为父类属性增加属性观察器,此时也需要使用override修饰

    代码:

    /*
     4、属性观察器重写
     */
    func test4() {
        class Circle {
            var radius: Int = 1
        }
        class SubCircle : Circle {
            override var radius: Int {
                willSet {
                    print("SubCircle willSetRadius",newValue)
                }
                didSet {
                    print("SubCircle didSetRadius",oldValue,radius)
                }
            }
        }
        let circle = SubCircle()
        /*
         SubCircle willSetRadius 10
         SubCircle didSetRadius 1 10
         */
        circle.radius = 10
    }
    test4()
    

    说明:

    1. let属性、只读计算属性不能增加属性观察器
    2. 如果是给父类的存储属性增加属性观察器,那么子类中只会继承父类的存储属性,没有变成计算属性。仅仅是增加了属性观察器
    3. 如果父类的存储属性也有属性观察器,子类也是可以重写的
    4. 也可以给父类的计算属性重写属性观察器

    3、总结

    注意:

    • 值类型(枚举、结构体)不支持继承,只有类支持继承
    • Swift中的类没有统一的基类,比如NSObject
    • 没有继承任何父类的类是基类,但其实它 是有一个父类的,叫_SwiftObject
    • 被final修饰的方法、下标、属性禁止被重写,被final修饰的类,禁止被继承

    总结:

    1. 重写除了一般的方法重写,还有下标重写、属性重写、属性观察器重写
    2. 其中下标、属性观察器、计算属性的重写本质上都是属于方法重写
    3. 只是注意一点可以将存储属性重写为计算属性

    相关文章

      网友评论

        本文标题:Swift基础语法(八)继承

        本文链接:https://www.haomeiwen.com/subject/ngjmurtx.html