第4章 类对象和接口
4.1 定义类继承结构
4.1.1 Kotlin中的接口
//接口定义
interface Clickable {
fun click()
}
//实现接口
class Button:Clickable{
override fun click() = println("I was clicked")
}接口的方法可以有一个默认实现。
interface Clickable {
fun click()
fun showOff() = println("I'm clickable!") //带默认实现的方法
}假设存在同样定义了一个showOff方法并且有如下实现的另一个接口。
interface Focusable {
fun setFocus(b: Boolean) =
println("I ${if (b) "got" else "lost"} focus.")
fun showOff() = println("I'm focusable!")
}类实现这两个接口,如果没有显式实现showOff,将会得到如下编译错误:
4.1.2 open、final和abstarc修饰符:默认为final
Java的类和方法默认是open的,而kotlin中默认都是final的。如果你想允许创建一个类的子类, 需要使用open修饰符来标示这个类。此外,需要给每一个可以被重写的属性或方法添加open修饰符。
如果重写了一个基类或者接口的成员,重写了的成员同样默认是open的,如果你想改变这一行为,阻止你的子类重写你的实现,可以显式地将重写的成员标注为final。
抽象成员始终是open的,所以不需要显式地使用open修饰符。
4.1.3 可见性修饰符:默认为public
4.1.4 内部类和嵌套类:默认是嵌套类
与Java不同,Kotlin的嵌套类不能访问外部类的实例。
4.1.5 密封类:定义受限的类继承结构
总是不得不添加一个默认分支很不方便。更重要的是,如果你添加一个新的子类,编译器并不能发现有地方改变了,如果你忘记了添加一个新分支,就会选择默认的选项,这可能导致潜在的bug。
Kotlin为这个问题提供了一个解决方案:sealed类。为父类添加一个sealed修饰符,对可能创建的子类做出严格的限制。所有的直接子类必须嵌套在父类中。
sealed修饰符隐含的这个类是一个open类,不再需要显式地添加open修饰符。
4.2 声明一个带非默认构造方法或属性的类
4.2.1 初始化类:主构造方法和初始化语句块
这段被括号围起来的语句块就叫作主构造方法,它主要有两个目的:表明构造方法的参数,以及定义使用这些参数初始化的属性。
constructor关键字用来开始一个主构造方法或从构造方法的声明。init关键字用来引入一个初始化语句块。因为主构造方法有语法限制,不能包含初始化代码,所以要使用初始化语句块。一个类中可以声明多个初始化语句块。
构造方法参数_nickname中的下划线用来区分属性的名字和构造方法参数的名字。另一个可选方案是使用同样的名字,通过this来消除歧义。
在这个例子中,不需要把初始化代码块放在初始化语句块中,因为它可以与nickname属性的声明结合。如果主构造方法没有注解或可见性修饰符,同样可以去掉constructor关键字。
如果不想类被其他代码实例化,必须把构造方法标记为private。