之前的篇章已经简单的介绍过如何声明一个类,也知道了一些简单的主构造方法来声明方法和属性,以及使用枚举类。
和Java相同的是,我们同样用interface来定义一个接口:
interface Clickable{
fun click()
}
除了定义,还需要学习如何实现一个接口:
class Button: Clickable{
//kotlin中重写一个方法使用override修饰符是强制的
override fun click() {
println("button is clicked!")
}
}
和Java相同的是,一个类只能继承自一个类,但是可以实现多个接口。
Kotlin在类名后使用了冒号来代替Java的extends和implements关键字。还有一点,就是Kotlin中,如果我们重写某一方法,必须强制使用override修饰符,这样做的好处就是避免了先写出实现方法后添加抽象方法的意外重写。
还有一点就是Kotlin中的接口可以自带默认实现的方法:
interface Clickable{
fun click()
fun showOff() = println("I'm clickable!")
}
如果实现该接口,我们必须重写click方法,而showOff不一定,如果你对原showOff行为满意可以不用重写直接使用,如果不满意重写即可。
我们假设定义了如下接口,和Clickable相同的是,我们同样写了一个默认方法showOff,一个类假如同时继承Clickable和Focusable但没有重写showOff方法,那么调用它的showOff方法会执行哪个呢?
interface Focusable{
fun setFocus(b: Boolean) =
println("I ${if (b) "got" else "lost"} focus.")
fun showOff() = println("I'm focusable!")
}
答案是,都不会执行,取而代之的是编译错误。
但是我们就有一个Button类实现了这两个接口,并且我们想使用Clickable的默认实现,该怎么办呢?
class Button: Clickable, Focusable{
override fun click() = println("button is clicked!")
override fun showOff() = super.showOff() //需要调用的基类的名字放在super后的<>内
}
我们可以调用super关键字访问基类,和Java不同的是,我们可以在super后使用<>符号显示的标明使用哪一个基类。
Java允许你创建人类的子类并重写任意方法,除非你使用final修饰符显示的标明。
Kotlin与之不同的是,Kotlin默认都是final类型的,也就是不可继承的,如果你想创建一个类的子,就需要用open修饰符来表示这个类。此外,需要给每一个需要被重回写的属性或者方法添加open修饰符。
例如:
open class RichButton: Clickable{ //这个类是open的,表明其他类可以继承
fun disable(){} //这个方法默认是final的,不能在子类中重写
open fun animate(){} //这个类是open的:可以在子类中重写
override fun click(){} //这个函数是重写了一个open的函数,并其本身也是open的
}
注意,如果你重写了一个基类或者是接口的成员,重写了的成员同样默认是open的。如果你想修改此行为,可以显式地使用final修饰符
open class RichButton: Clickable{ //这个类是open的,其他类可以继承
final override fun click(){} //这里显式地使用final,标明该方法禁止重写
}
和Java一样,可以使用abstract来表明一个类不能被实例化。一个抽象类通常包含一些没有实现且强制子类重写的抽象成员,它们默认是open的,不需要显式的使用open修饰符。
abstract class Animated{
abstract fun animate() //abstract的函数必须被子类重写
open fun stopAnimating(){} //抽象类中的非抽象函数并非默认open的,但可以标注为open
fun animateTwice(){} //final类型的非抽象函数
}
接下来总结一下Kotlin中的访问修饰符:
修饰符 | 相关成员 | 评注 |
---|---|---|
final | 不能被重写 | 类中成员默认使用 |
open | 可以被重写 | 需要明确的标明 |
abstract | 必须被重写 | 之后在抽象类中使用,抽象成员不能有实现 |
override | 重写父类或者接口的成员时使用 | 重写的成员默认是open的,如果之后不想被重写可以显示使用final |
Kotllin的可见性修饰符和Java中的类似。同样可以使用public,private,protected修饰符,但是默认的可见性不一样,Kotlin默认为public类型,Java默认为包私有。
另外,Kotlin提供了一个新的修饰符internal,表示“只在模块内部可见”,这个模块是一组一起编译的Kotlin文件。有可能是一个IDEA模块,一个Eclipse项目,一个Maven或者是Gradle项目。
还有一个区别就是Kotlin允许在顶层声明中使用private可见性,包括类,函数和属