【Kotlin从入门到深坑】之类的覆盖属性和方法以及抽象类

简介

本篇博客主要是介绍Kotlin语法中的【类的覆盖属性和方法以及抽象类】相关的知识,帮助各位更快的掌握Kotlin,如果有疏漏或者错误,请在留言中指正,谢谢。 系列汇总地址


上一篇博客中我们详细介绍了类的继承和构造,下面我们来讲一下,在继承时如何覆盖方法。


覆盖方法

我们先看一下如何去写,例子如下:

// 父类,使用open关键词
open class TestB {
   open fun test() { //需要被重写的方法需要使用open修饰
        
    }
}
//子类
class TestA() : TestB() {
    override fun test() {//重写的方法需要使用override
        super.test()
    }
}

方法和类一样,默认是final的禁止重写的,所以必须加上open修饰,而重写的方法也必须加上override,否则子类不允许相同签名的函数。

还有一点是需要注意的,默认override的函数是open的,如果你想再次限制它被覆盖,可以使用final修饰,代码如下:

//子类
class TestA() : TestB() {
    final override fun test() {//重写的方法需要使用override,使用了final,后续无法覆盖
        super.test()
    }
}


覆盖属性

我们先看一下如何去写,例子如下:

//父类
open class TestB {

   open var x: Int? = null //属性x
        get() {//重写了get方法,此处后面详解
            field = 34
            return field
        }
}

class TestA() : TestB() {
    override var x: Int?=null //它覆盖对应属性后,对应的方法也被覆盖
    

}

对于Kotlin中的属性都有默认的get、set方法,当然也可以重写,比如上面的TestB的x的属性的get方法被重写了。但是TestA 覆盖属性后,TestB中定义的get方法对其无效,举例如下,便于理解其含义:

 var a = TestA()
    println(a.x)

    var b=TestB()
    println(b.x)

输出结果:

null  //说明TestB的get方法对TestA类无效
34   //说明TestB的get方法对TestB类有效

注意:如果原类型为var,则覆盖类型可以为var,且不可以是val,如果原类型是val,覆盖类型可以是val,也可以是var


多实现

在Kotlin中,对于继承来说,如果一个类从它的直接超类继承相同成员的多个实现,它必须覆盖这个成员并提供自己的实现。为了表达�采用从哪个超类型继承实现,我们使用super<父类名>,下面举例说明:

//首先声明一个类
open class TestB {

   open var x: Int? = null
        get() {
            field = 34
            return field
        }

    open fun test() { //此处有一个可以覆盖的方法test()

    }


}
//声明一个接口
interface TestC { //这个是接口的声明方式
    var x: Int? //声明了一个抽象字段,实现类必须覆盖此属性
    fun test() { //声明了一个方法,这个是特殊的,可以有实现方法
        print("d")
    }

    fun test2() //这个是和java一致的抽象方法
}

此处需要注意此处的接口是可以实现具体的方法的

//实现类TestA
class TestA() : TestC, TestB() {

    override fun test2() {//对于一般的抽象方法等同于java中,必须实现,否则声明成抽象类

    }

    override fun test() {//此处必须写,因为test有两种不同实现
        super<TestC>.test()
        super<TestB>.test()
        //上面两个都可不写,也可以都写,类似于super.method

    }

    override var x: Int? = null //对于字段没影响,因为接口的属性不允许赋值,


}

我们总结一波:

  • 首先继承TestBTestC是正常的
  • 由于TestBTestC内都有test方法,所以TestC必须实现test方法
  • 在子类TestC中使用super<TestB>.test()或者super<TestC>.test() 来调用父类的实现

上面我们说的是方法,仔细的话,我们还能看到接口还有属性的定义,对于TestBTestC都有x字段,TestA中进行重写的话,get/set都会被覆盖,所以不会出现上面方法的问题

还需要注意,看一下代码

open class TestB {//类的一个成员变量
    open var x: Int? = null
}

interface TestC { //这个是接口的声明方式
    var x: Int? //声明了一个抽象字段,实现类必须覆盖此属性

}

//实现类
class TestA() : TestC, TestB() {
}

我们总结一波:

  • 对于接口来说,他的方法默认是抽象的,除非自己实现了
  • 对于接口的成员变量也是一样的,也是默认抽象的,子类必须覆盖
  • 但凡事都有例外,对于上面的实现中,我们并没覆盖x,但仍然正确是,因为,接口只是约束作用,因为TestA继承了TestB,也就有了X,字段,而接口也就是约束必须有该字段即可,所以,上面的实现也是允许的

抽象类

类和类中的某些成员可以声明成abstract ,抽象成员在本类中可以不去实现,需要注意的是我们不需要用open标注抽象类或者函数,更有趣的是看如下实现:

//开放的类和方法
open class A{
    open fun  test(){
        
    }
}
//抽象类
abstract class B : A() {
    abstract override fun test() //抽象方法覆盖开放方法
}

我们可以用一个抽象成员去覆盖一个非抽象的开放成员


伴生对象

与java不同,Kotlin没有静态方法,官方建议使用包级函数,可以使用如下两种方式来实现类似静态类、静态方法的方式
第一种:

object StaticDemo{
    fun test(){
        print("")
    }
}

使用方法如下:

  StaticDemo.test()

第二种:

class Demo {
    companion object {//声明在内部的,类似静态方法,可以使用 类名.方法名
        fun test() {
            print("")
        }
    }

    fun test2() { //test2在外部,必须实例化后才可调用
        
    }

}

使用方法:

  Demo.test()

下面我们总结一波:

  • 无论方法还是类除了抽象类、抽象方法、接口、接口方法外,其他的继承都需要写open,重写的成员变量和方法需要override

  • 与java不同,Kotlin中的接口可以自己实现方法,从而导致了出现多实现的问题,出现多实现的,继承的子类需要重写对应的方法,然后决定是否或者调用哪个父类的方法。


总结

至此已经学完了Kotlin的【类的覆盖属性和方法以及抽象类】相关的知识,多回顾多思考,继续后续内容

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

推荐阅读更多精彩内容

  • Kotlin的类和接口与Java的类和接口是有一定的区别的。Kotlin的接口是可以包含属性声明。Kotlin默认...
    程自舟阅读 10,246评论 0 11
  • 前言 人生苦多,快来 Kotlin ,快速学习Kotlin! 什么是Kotlin? Kotlin 是种静态类型编程...
    任半生嚣狂阅读 26,062评论 9 118
  • 原文链接:https://github.com/EasyKotlin 在前面的章节中,我们学习了Kotlin的语言...
    JackChen1024阅读 830评论 0 3
  • 经历过几次生死攸关的时刻,对死亡就相当恐惧。曾以为,死亡是离自己多么遥远的事情,到了真正亲临的那一刻,你就会明白,...
    弋筠阅读 929评论 4 7
  • 夏日的风,有些潮湿 来到了夏与秋的交际 回想我们一起走过风雨 走过白雪皑皑的冬夜 也走过春光明媚的丽日 那次走到了...
    紫色人生阅读 258评论 4 3