小狮子的Kotlin学习之路(十)

Kotlin接口

这一篇我们了解Kotlin的接口。还记得很早之前看过一篇大神的博客,说接口就是特殊的抽象类,其实我个人也是比较认可这种说法的,尤其是在Kotlin语言中。

接口声明语法:interface IfaceName {}

接口默认是open的,因此不需要再open关键字修饰。

interface KotlinIface {
}

同样地,在接口中声明的函数,默认也是openabstract的。在Idea编辑器中,如果加上open或者abstract,编辑器就会提示多余的修饰符。

接大神博客中的说法,接口就是抽象到类中的所有函数都是抽象的。当然,这还是当年针对Java的描述,在Java8之后,接口也是允许有默认的函数实现的。(这种暴露年龄的话,好像不应该说。。。)

Kotlin中,接口也是可以有默认的函数实现的。

interface KotlinIface {
   fun show(msg: String)   // No implementation.

   fun read()

   fun defaultImpl() {  // Default implementation.
       show("default show.")
  }
}

接口一般仅作为某个对象或者对象群的行为定义的,并不做具体实现。因此,接口必须是有对应的类来做实现的。当然实现也有部分实现和完全实现。

一般地,一个类实现某个接口,就必须实现接口中所有的抽象函数。

class KIfaceImpl : KotlinIface {
   override fun show(msg: String) {
  }

   override fun read() {
  }

但是如果实现接口的类是抽象的,即抽象类实现的,则可以实现接口部分需要的函数即可。

abstract class AbsKIfaceImpl : KotlinIface {
   override fun show(msg: String) {      
  }
}

如果实现接口的类是抽象类,则可以选择性的实现接口的零个或全部函数。

类继承是只能继承单个父类的,但是接口却可以同时实现多个接口。这弥补了单继承的缺点。

interface KIface {
   fun write()
}

比如我们定义新的接口KIface,让KIfaceImpl同时实现两个接口。

class KIfaceImpl : KotlinIface, KIface {
   override fun show(msg: String) {
  }

   override fun read() {
  }

   override fun write() {
  }
}

我们学习了接口的定义及接口中函数的定义,既然作为一个特殊的抽象类,接口中也是可以定义属性的,但是接口中的属性只能是抽象的,通俗点就是不能赋值的。同样地,和函数一样,默认是open修饰的。

interface KIface {
   val name: String
   
   fun write()
}

和函数一样,实现接口的类,必须提供属性的实现。而对于属性来说,就是它getset方法的实现。

class KIfaceImpl : KIface {
   override val name: String
       get() = "KIface"

   override fun write() {
  }
}

一个类实现了某个接口,那这个类也就是这个接口的一个实例。

class KIfaceImpl : KIface {
   override val name: String
       get() = "KIface impl."

   override fun write() {
       println("KIface impl write.")
  }
}

我们实现了KIface接口并实现了它的属性和函数。我们来运行一下:

fun main() {
   val kIface: KIface = KIfaceImpl()
   println("name = ${kIface.name}")
   kIface.write()
}

main方法中,我们声明了KIface的对象,但是实际创建的是KIfaceImpl对象。

执行之后的输出结果:

关于Kotlin接口的基本内容就这么多,但是有一个比较特殊的使用场景。比如,我们一个类实现了两个接口,但是两个接口中存在同样的函数声明,那这种情形下,关于函数的实现及调用是什么样子的呢?

interface KIfaceA {
   fun a() {
       println("KIfaceA -> fun a().")
  }

   fun b()
}

interface KIfaceB {
   fun a() {
       println("KIfaceB -> fun a().")
  }

   fun b() {
       println("KIfaceB -> fun b().")
  }
}

我们在两个接口中同时有a()函数和函数b(),并且函数声明一样。

我们使用一个类同时实现这两个接口。

class ClassC : KIfaceA, KIfaceB {
   override fun a() {
  }

   override fun b() {
  }
}

在这里,虽然两个接口中仅有一个未实现的函数,但是在ClassC中,必须要实现两个函数。

编译器提示,必须重写函数a()因为它继承自多个接口。

class ClassC : KIfaceA, KIfaceB {
   override fun a() {
  }

   override fun b() {
  }
}

那问题又来了,我们怎么样调用接口中的默认实现的函数呢?

强大的编译器给我们提示,你需要使用像super<Foo>这样的方式调用。

class ClassC : KIfaceA, KIfaceB {
   override fun a() {
       super<KIfaceA>.a()
       super<KIfaceB>.a()
  }

   override fun b() {
       super.b()
  }
}

仔细的同学会注意到,函数b()的调用并没有像函数a()一样,这是因为接口中并不存在两个同样的实现,调用父类的函数时,只能调用已经实现的函数。

下一篇,我们将继续学习一些Kotlin的特殊类。

微信扫码关注,惊喜多多

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值