类对象和接口
1 定义类继承结构
1.1kotlin中的接口
声明一个接口:
interface Clickable{
fun click()
}
实现一个接口:
class Button: Clickable{
override fun click() = print("clicked")
}
kotlin中用冒号代替extends和implements,用override代替@Override。
kotlin的接口同样可以有一个默认的实现,且不需要标注default关键词。
如果你继承的两个接口实现了同样的方法,在类中调用该方法时会得到一个编译错误,你需要提供自己的实现。
//指定调用哪一个接口的方法
override fun click(){
super<Clickable>.click()
}
1.2 open、final、abstract修饰符:默认为final
kotlin中类和方法默认是final的,如果你想要让这个类课被继承,你需要用open来修饰这个类。并给类中每一个可以被重写的属性或方法添加open修饰符。
如果你重写了一个基类或接口,重写的成员默认是open的。如果你想改变这个行为,你可以显式的将成员标注为final。
抽象类始终是open的。
1.3 可见性修饰符:默认为public
kotlin中没用java中的默认可见性(包可见),但kotlin提供了internal(在模块内部可见)用来代替。一个模块就是一组一起编译的kotlin文件。
修饰符 | 类成员 |
---|---|
public | 所有地方可见 |
internal | 模块中可见 |
protected | 子类中可见 |
private | 类中可见 |
注意 扩展函数不能访问类的private成员和protected成员
1.4 内部类与嵌套类
我们知道内部类会持有外部类的引用,java中在其他类中声明的类默认是内部类,而kotlin中默认是嵌套类,不持有外部类的引用,类似于静态内部类。
1.5 密封类:定义受限的类继承结构
密封类对可能创建的子类做出了严格的限制。
sealed class Expr{
//将所有可能的类作为嵌套类列出
class Num(): Expr()
class Sum(): Expr()
}
2 类的构造方法
2.1 初始化类: 主构造方法和初始化语句
class User(val nickName: String){
init{
nickName = "zhangqiang"
}
}
User后面括号中的语句就是主构造方法,主要为了表明构造方法的参数,以及定义使用这些参数初始化的属性。
//你也可以把constructor关键词写出来,并将类设为私有
class User private constructor(val nickName: String)
2.2 从构造方法
你可以声明多个从构造方法
open class View{
constructor(ctx: context) {
}
constructor(attrL AttributeSet){
}
}
2.3 object关键字
object关键字定义一个类并同时创建一个实例。
使用场景:
- 对象声明定义单例
- 伴生对象可以持有工厂方法和其他与这个类相关,但在调用时并不依赖实例的方法。可以通过类名来访问
- 对象表达式来代替java的匿名内部类
2.3.1 对象声明创建单例
object Payroll {
val allEmployees = arrayListOf<Person>()
}
对象声明通过object关键字引入,一个对象声明可以非常高效地以一句话来定义一个类和一个该类的变量。
和类一样,一个对象声明也可以包含属性、方法、初始化语句块等声明。唯一不允许的就是构造方法。因为对象声明在定义的时候就立即创建了实例,不需要调用构造方法。
2.3.2 伴生对象
java的static并不是kotlin语言的一部分。作为替代,kotlin提供了顶层函数和对象声明。但是顶层函数不能访问类的私有成员,kotlin提供了companion来解决这个问题。
//声明
class A{
companion object{
fun bar() {print("companion object")}
}
}
//调用
A.bar()
companion修饰的对象或方法可以直接通过类名来调用,类似java中的static。它是与私有化构造方法一起实现工厂模式的理想选择。你也可以通过伴生对象来定义扩展函数,实现通过对象实例调用的扩展函数。
2.3.3 对象表达式
object关键字也可以用来声明匿名对象。
window.addMouseListener(
object: MouseAdapter(){override fun mouseClicked(e: MouseEvent){}
}
}