关于Kotlin中抽象类和接口的一点总结
抽象类和接口
一、Kotlin中的接口
定义上:
Kotlin中的接口跟Java8是很类似的,可以包含抽象方法的定义也可以包含抽象方法的实现,但是不包含任何状态。
语法规则上:
interface关键字用来修饰Kotlin中的接口,这个和java类似的
interface Clickable{
fun click()
}
使用的时候是这样的
class Button :Clickable{
override fun click()=println("I was clicked")
}
这里有需要注意的点,
(1)、Kotlin是使用:来表示继承和实现的,这个区别于java
(2)、另外 override 是Kotlin里的关键字,在java那边是属于复写的注解,Kotlin里这个关键字使用是强制要求的。
(3)、java 8的接口里的默认实现的方法是用 default关键字来修饰的,Kotlin中并不需要。
(4)、Kotlin和java中接口里的静态方法都是用接口直接调用,不能使用实现他的子类来调用,这里要注意的是java里的静态方法是这样定义的
//java中的静态方法
class TestMode{
static void show(){
println("静态方法");
}
}
//Kotlin中的静态方法
class TestMode2{
companion object{
fun showOff2()=println("来自静态方法")
}
}
(5)、Kotlin中实现的多个接口中,有相同的默认实现的方法的,子类一定要复写该方法,这个和java保持一致。其实就是为了让子类自己来决定他到底要调用哪个接口中的方法。子类必须复写该方法,如果子类在复写的方法中要调用接口的实现,Kotlin和java在语法上有些区别
//Kotlin 类似下面
super<TestMode>.show()
//java 类似下面
TestMode.super.show()
(6)、Kotlin的接口中的成员始终是open的,不能将其声明为final。
二、Kotlin中的抽象类
我们需要简单了解下Kotlin中的类修饰符
修饰符 | 说明 |
---|---|
final | 不能被继承 |
open | 可以被继承 |
abstract | 抽象类 |
enum | 枚举类 |
data | 数据类 |
sealed | 密封类 |
annotation | 注解类 |
我们知道java中的类默认是可以被继承的,除非我们显式的生命了final类,这其实是违背优秀的java编程风格的,虽然在《Effective Java》中明确强调了我们设计的基类如果不是为了继承而设计,我们应该毫不犹豫的将其声明为final类,但是到今天,我们Java程序员的编程风格中显然是没有按照这个风格进行的。Kotlin是遵从了这个设计风格的,Kotlin的类默认是final的。在Kotlin中如果想让该类可以被继承那就需要显式的将其声明为open,
我们要说的是抽象类所以abstract是必不可少的了,这和java是保持一致的,Kotlin中抽象类的成员默认是open的,这里有需要注意的点,如果函数没有方法体,他就是抽象的,但是abstract关键字不是必须的(这里可能有点歧义,我所说的比如接口中的方法,并没有用abstract修饰)。
三、Kotlin中抽象类和接口的区别
这个其实跟java语言中设计抽象类和接口的区别是大同小异的,抽象类还是在类的层面上来看问题的,具有自己的构造方法和成员变量和成员方法,是在类的基础上的一种抽象,日常项目开发中把我们需要的一些通用方法尽量上移,把一些需要不同实现的方法,也上移,这个时候我们使用抽象类,就可以很好的来解决这个问题,接口可以理解为对行为的一种抽象,对一类行为的(方法)的抽象,接口的设计是为了解耦的,单独的依靠抽象类,并不能将定义和实现很好的分离开来,一味的在抽象类中新加含有具体实现的方法,其实是对不需要该方法的子类的一种污染,一味的新加抽象方法,也需要对子类不断的更改,这个时候我们使用接口来定义这种行为,在需要的子类中实现该接口,就可以很好的处理这个问题。
Kotlin设计接口是为我们提供一种将接口和实现分离的更加结构化的方法。抽象类是接口和普通类之间的一种中庸之道,但是两者都有其存在的意义。抽象类和接口在设计模式以及解耦方面有着不可替代的作用。这也是大部分面向对象的语言都有抽象类和接口设计的原因,也是为了弥补无法多重继承的遗憾。