kotlin入门潜修之类和对象篇—接口

本文收录于 kotlin入门潜修专题系列,欢迎学习交流。

创作不易,如有转载,还请备注。

接口

kotlin中的接口和java 8非常相似,可以定义抽象方法也可以定义方法实现,定义接口的关键字是interface。示例如下(请仔细阅读代码注释,很多情形基本都包含了):

interface MyInterface {

    val val1: Int//正确,接口中的所有属性都默认为abstract
    abstract val val2 : Int//正确,这里显示定义了abstract,实际上是多余的

    var var1: Int//同上
    abstract var var2 : Int//同上

    private var var3: Int//错误,private与默认的abstract修饰符冲突(val也一样)
    private var var4: Int = 1//错误,接口中的变量(val也一样)都无法初始化

    val var1: Int//正确,可以提供get实现
        get() = 1

    var var2: Int//错误,接口中不能包含后备字段field
        get() {
            field = 1
        }

    fun m1()//正确,接口中的所有没有实现的方法都默认为abstract
    abstract fun m3()//正确,但abstract是多余的
    private fun  m5()//错误,接口中没有body的方法默认是abstract的,这个字段与private是冲突的,无法同时存在

    fun m2() {//正确,非抽象方法,因为这里提供了实现
        println("m2 method")
    }

    private fun m4() {//正确,非抽象方法可以使用private修饰
        var1 = 2
    }

}

上面代码中已经对接口中的各个情况做了很好的说明,这里不在展开说明。

接口的实现

kotlin不再像java那样,提供了implements关键字来实现,而是同继承一样,使用冒号(:)即可:

//接口的定义
interface MyInterface {
    fun m1()//注意,m1默认是abstract的
    fun m2() {//m2不在是abstract,这里提供了默认实现
        println("m2 method")
    }
}
//实现接口
class InterfaceTest : MyInterface{
    override fun m1() {//这里因为接口中的m1方法是abstract的,所以子类必须要实现,m2方法就没有必要,因为接口已经有默认实现
        throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
}

接口继承

kotlin中的接口是可以继承接口的,这点和java一样,java也允许一个接口继承(extends)另一个接口(注意不是实现implements)。kotlin中接口继承接口示例如下:

//第一个接口MyInterface
interface MyInterface {
    fun m1()//抽象方法
    fun m2()//抽象方法
    fun m3() {//有默认实现
        println("m2 method")
    }
}
//第二个接口,继承了MyInterface接口,并实现了m1
interface MyInterface2 : MyInterface {
    override fun m1() {//注意这里实现了m1方法
        throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
}
//具体的实现类,实现了MyInterface2接口
class InterfaceTest : MyInterface2{
    override fun m2() {//这里必须要实现m2方法
        throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

}

上面代码中,InterfaceTest必须要实现m2方法,而没有实现m1方法,这是为什么?

因为在MyInterface2接口中已经复写了m1方法,提供了其默认实现,也就是此时m1已经不是abstract方法了,所以InterfaceTest就没有必要进行强制实现了。而m2方法MyInterface并没有提供实现,MyInterface2接口也没有进行实现,所以InterfaceTest必须要实现。

那么为什么MyInterface2可以不实现m2而InterfaceTest必须要实现呢?

因为MyInterface2本身是个接口,可以提供abstract方法,而InterfaceTest已经是个具体的类,因此它必须要实现父接口中未实现的方法,除非InterfaceTest为抽象类(即用abstract修饰)。对于属性的继承规则和方法基本一致。

复写冲突

复写冲突,其实在文章kotlin入门潜修之类和对象篇—继承
的类复写规则中已经介绍过了,只不过现在变成了接口,简单介绍如下。

所谓复写冲突,是指在一个子类中,实现了多个父接口,而不同的父接口又拥有相同的方法签名,这就给子类实现造成了冲突,子类无法确认调用那个父接口的实现。

复写冲突示例如下

//interface1接口
interface Interface1 {
    fun m1() {//注意m1方法已经有默认实现,理论上不再强制子类实现
        println("m1")
    }

    fun m2()//会强制子类实现该方法
}
//inteface2接口
interface Interface2 {
    fun m1() {//注意m1方法已经有默认实现,理论上不再强制子类实现
        println("m1")
    }

    fun m2() {//注意m2方法也已经有默认实现,理论上不再强制子类实现
        println("m2")
    }
}

//实现类
//这里InterfaceTest同时实现了Interface1, Interface2 两个接口
class InterfaceTest : Interface1, Interface2 {
    override fun m2() {//注意这里必须要实现m2方法,是因为Interface1中m2方法没有被实现。
        super.m2()//这里的super调用的实际上就是Interface2中方法,Interface1并没有该方法实现。
    }

    override fun m1() {//这里必须要实现m1方法,是因为虽然Interface1和Interface2中都已经实现了m1,但是这给子类实现带来了冲突,如果不实现就无法确认该调用Inteface1中的m1实现还是应该调用Intreface2中的实现,故kotlin强制子类实现m1方法
        super<Interface1>.m1()//通过这种形式来指定调用那个父接口的方法,这里调用Interface1接口中的m1方法
        super<Interface2>.m1()//这里调用Interface2接口中的m1方法
    }
}

抽象类和接口对比

这里我们对抽象类和接口进行下对比,因为二者实在太过于相似。抽象类我们在kotlin入门潜修之类和对象篇—继承中已有所阐述,这里姑且总结下二者的差异,朋友可以自行验证。

  1. 接口中属性默认都是abstract的,而抽象类中的属性默认是非abstract,需要显示定义为abstract

  2. 接口可以包含abstract方法,也可包含非abstract方法,如果方法没有方法体则默认是abstract的;抽象类中同样可以包含abstract方法以及非abstract方法,如果抽象类中的方法没有方法体则必须使用abstract显示声明。

  3. 接口中,属性是无法进行初始化,但是抽象类中的非abstract方法可以进行初始化。

  4. 一个class只要含有abstract的属性或者方法,该类就必须被声明为抽象类,即要使用abstract修饰。

  5. 一个class可以实现多个接口,但是一个class只能继承一个类。

接口和抽象类的使用场景

接口和抽象类都是kotlin(java也是)中实现多态的重要一部分。在应用开发的过程中,合理的利用接口和抽象类,有利于我们设计出高内聚低耦合的系统,以让系统有更好的扩展性、健壮性。二者的使用场景总结如下(实际上这也是很多其他面向对象语言的特性):

  1. 一般情况下我们不会在接口中定义属性,这样做基本没有太大意义,更多的是定义行为(即方法),如果需要用到属性则建议使用抽象类

  2. 由于kotlin中是单继承的,所以抽象类有天生的弊端,即其子类无法再继承其他的类;而接口则可以实现多个,因此如果抽象类中都是抽象的方法则建议使用接口替换。

  3. 从面向对象的角度来看,类是对某一个对象的属性和行为的抽象,而接口更多的是增加一些功能行为。因此,如果子类想扩展功能行为则应考虑使用接口,否则应使用抽象类。

  4. 抽象类实际上是基于当前类进行的一层抽象,更多的是表达子类共有的行为,而接口如3中所言是功能性增强。二者产生的背景是不一样的,一个是基于现有的抽象,一个是基于现有的扩充。因此,也可以从这个角度出发,选择到底是用抽象类还是接口。

具体采用哪种实现,可根据实际场景进行选择。

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

推荐阅读更多精彩内容

  • 本文收录于 kotlin入门潜修专题系列,欢迎学习交流。 创作不易,如有转载,还请备注。 继承 面向对象的三大基石...
    寒潇2018阅读 848评论 0 3
  • Kotlin的类和接口与Java的类和接口是有一定的区别的。Kotlin的接口是可以包含属性声明。Kotlin默认...
    程自舟阅读 10,324评论 0 11
  • 写在开头:本人打算开始写一个Kotlin系列的教程,一是使自己记忆和理解的更加深刻,二是可以分享给同样想学习Kot...
    胡奚冰阅读 1,415评论 5 11
  • 扩展 Kotlin 的扩展是一个很独特的功能, Java本身并不支持扩展, Kotlin 为了让扩展能在JVM平台...
    凌寒天下独自舞阅读 720评论 0 0
  • 春夏交际,草长莺飞,鸟语花香。昆虫们也出来玩耍了。 一直小蜜蜂落在一朵牵牛花上,看到旁边的草叶上趴着一直小蚂蚱。 ...
    乌卓阅读 725评论 5 5