4.1 接口的定义
接口使用
interface
关键字,kotlin中的实现和继承使用:
冒号代替implement
和extend
接口定义
//包含一个抽象方法,这个抽象方法有默认的实现
interface Clickable{
fun click() = println("cat is clicked")
}
接口的实现
class Cat :Clickable{
//实现接口里的抽象方法
override fun click() {
}
}
如上,kotlin接口的抽象方法可以有一个默认实现,此时子类可以不用实现这个方法,默认调用父类里的方法实现
注意:如果我们实现了有重名方法的两个接口,此时必须提供自己的方法实现
interface Clickable{
fun click() = println("cat is clicked")
}
interface Focusable{
fun click() = println("cat is focused")
}
class Cat :Clickable,Focusable{
override fun click() {
super<Clickable>.click()
super<Focusable>.click()
}
}
使用super<Clickable>.click()
调用接口的方法的实现,在尖括号里指明调用的基类的名称
4.2 继承控制修饰符
Java中所有的类和方法默认是open的,可以继承和重写的。但是kotlin中默认是final的,如果想创建一个子类,需要用open来修饰这个类。而且,需要给每个需要被重写的方法和属性添加open修饰符
修饰符 | 相关成员 | 备注 |
---|---|---|
final | 不能被重写 | 类中的成员默认使用 |
open | 可以被重写 | 需要明确的声明 |
abstract | 可以被重写 | 修饰抽象类,修饰的抽象成员不能有实现 |
override | 修饰重写的父类的方法或者参数 | 如果没有使用final修饰,这个重写的成员还是开放的即open的 |
//使用open修饰符修饰的类才能被继承
open class Dog(){
}
4.3 可见性修饰符
Kotlin中的可见性修饰符同样可以使用:public、protected、private,默认可见性为public
- Java中的默认可见性是-包私有,Kotlin只是把包作为代码的组织方式,并没有做可见性的控制
- Kotlin中提供了一种新的修饰符internal,表示模块内部可见,一个模块理解为一起编译的Kotlin文件
- Kotlin允许在顶层声明中使用private关键字,包括类、函数和属性,只在声明他们的文件中可见
修饰符 | 类成员 | 顶层声明 |
---|---|---|
public(默认) | 所有地方可见 | 所有地方可见 |
internal | 模块中可见 | 模块中可见 |
protected | 子类中可见 | - |
private | 类中可见 | 文件中可见 |
4.4 内部类和嵌套类
Kotlin中可以把类定义在其他类中,但是默认是不持有外部类的引用的,叫嵌套类
想要从嵌套类中访问外部类的引用,需要使用inner
修饰符将其定义成内部类,如下
/**
* 1.Kotlin中类可以嵌套在其他类中,默认是静态内部类
* 2.使用inner修饰的内部类为非静态内部类,才可以访问外部类的参数和引用
* 3.inner修饰的内部类访问外部类的引用时,可以用this@外部类 的方式访问
*/
class OuterClass() {
val name: String = "haha"
inner class Inner {
fun getOutParam() = name
fun getOutClass() = this@OuterClass.name
}
}
4.5 密封类
密封类,用来表示受限的类继承结构:当一个值为有限集中的类型、而不能有其他类型时。
声明一个密封类,用sealed
修饰符,而且其子类要和这个密封类定义在同一个文件中
sealed class Animal
class Fish() : Animal()
class Sheep() : Animal()
fun switchAnimal(animal: Animal) =
when (animal) {
is Fish -> println("this is a fish")
is Sheep -> println("this is a sheep")
}
如上,密封类的关键好处在于使用when
表达式时,如果验证语句覆盖了所有的情况,那么我们不需要再提供else
子句了。
4.6 构造函数和初始化块
Kotlin中构造函数由一个主构造函数和多个从构造函数组成
主构造函数: 是类头的一部分,定义在类名后面
class Apple constructor(val size:Float,val color:Int)
当主构造函数没有注解或者可见性修饰符修饰时constructor
可以省略,由于主构造函数不能包含任何代码,初始化等代码可以放在初始化块中init{}
//省略constructor关键字
class Apple(val size:Float,val color:Int){
init {
//初始化代码
}
}
从构造函数:可以声明多个前缀为constructor
的从构造函数
自定义view通常要写几个构造函数,MyButton
有三个从构造函数,没有主构造函数
class MyButton : View {
//使用this委托给两个参数的构造函数
constructor(context: Context) : this(context, null)
//使用this委托给三个参数的构造函数
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
//使用super调用父类的构造函数,初始化其基类
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
}
}
如果类没有主构造函数,那么每个从构造函数必须使用super
关键字初始化其基类,或者委托另一个构造函数做到这一点。
网友评论