Swift基础语法(八)继承

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. 只是注意一点可以将存储属性重写为计算属性
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容