- 继承
- 接口,和Java8类似(可以包含抽象方法和非抽象方法)
interface Clickable{ // 一个典型接口 fun click() fun showOff() = println("Interface Clickable") } interface Focusable{ fun onFocus() fun showOff() = println("Interface Focusable") } class Button: Clickable, Focusable{ override fun click() = Unit override fun onFocus() = Unit //当继承的接口非抽象方法重复,且该方法都为非抽象方法时,子类必须实现该方法 override fun showOff(){ //此时编译器不知道应该调用那个方法,所以必须实现 super<Clickable>.showOff() // super<接口名>.method调用特定接口方法 super<Focusable>.showOff() } } // Java中实现有默认实现的接口 class T implements Clickable{ @Override public void click() {} @Override public void showOff() { Clickable.DefaultImpls.showOff(this); } }
- 继承接口相关修饰符:open,abstract,final,默认为final
修饰符 | 相关成员 | 评注 |
---|---|---|
final | 不能被重写 | 类中的成员默认使用 |
open | 可以被重写 | 需要明确表明 |
abstract | 必须被重写 | 只能在抽象类中表明,抽象成员不能有实现 |
override | 重写父类或接口的成员 | 若无final声明,默认开发 |
class Obj() // 不可继承
open class Obj : Clickable{ //加了open修饰符,可以继承
fun method(){} //不可重写
open fun method //可重写
override fun click() {} //重写的open方法,可重写
}
abstract class Obj { //可以继承
abstract fun method(){} //可重写
fun method(){}//不可重写
open fun method //可重写
}
- 可见性相关修饰符:public(默认),private,internal,protected
这里和Java有些不同:- Java可以访问共同一个包的其他类protected属性,internal到Java中会变成public,在Java中调用Kotlin会访问到在Kotlin中不能访问的属性
修饰符 | 类成员 | 顶层声明 |
---|---|---|
public | 所有地方可见 | 所有地方可见 |
internal | 模块可见 | 模块可见 |
protected | 子类可见 | - |
private | 类可见 | 本文件可见 |
- 默认内部类,是静态的内部类,添加inner修饰符可以将内部类变成实例内部类
class Outer{ inner class Inner{ fun getOuterReference() : Outer = this@Outer //kotlin持有外部类引用的方式 } }
- kotlin特有密封类 通过sealed修饰的类子类只能在他的内部
//一个应用场景 sealed class Expr{ //需要sealed声明 class Num(val value: Int) : Expr() class Sum(val left: Expr,val right: Expr): Expr() } //包含所有场景,不用担心出现忘记处理异常 fun eval(e: Expr): Int = when (e){ is Expr.Num -> e.value is Expr.Sum -> eval(e.left) + eval(e.right) }
- 类的构造方法
- 明确写法
class User(val name: String) 等同于,下面最明确的写法 class User constructor(_name: String){ //constructor主构函数或从构函数 val name: String init{ //初始化代码块 name = _name } } class User{ //从构造方法的使用 constructor(name: String){...} constructor(name: String,age: Int){...} }
- 继承与构造方法
class Child(param: String) : Father(param) {...} //必须调用父类的构造方法 class Child : Father() //子类无构造方法必须显示调用父类构造方法
- 私有构造方法
class Obj private constructor(){}
- 接口的属性
interface User { val name: String //必须重写 val age: Int //可继承 get() = 10 } //三种实现方式 class Student1(override val name): User class Student1: User{ override val name: String get() = "" } class Student1: User{ override val name: String = "" }
- 私有的setter:
class Obj { var counter: Int = 0 private set }
- 编译器生成的方法:数据类和类委托
- 在kotlin中可以用 === 比较对象的引用
- 数据类(天然的不可变对象)
默认包含toString,hashCode,equals方法(使用的是主构函数的参数) - 类委托: by 关键字
// 实现一个装饰器 // 记录给set加了多少次元素 class CountingSet<T>( val innerSet: MutableCollection<T> = HashSet<T>() ): MutableCollection<T> by innerSet { // 这个类包含了所有MutableCollection的可继承属性 var objAdded = 0 override fun add(e: T) : Boolean{ objAdded++ return innerSet.add(e) } override fun addAll(list: Collection<T>) : Boolean{ objAdded += list.size return innerSet.addAll(list) } }
- object 关键字
功能: 声明类的时候创建实例object Obj { //无构造方法 val param: Int = 1 fun method() = 2 } Obj.param // 1 Obj.method() //2
- 伴生对象:工厂方法,静态方法
class A { companion object{ //注意companion关键字,伴生对象可实现接口继承对象 fun foo() = 1 //相当于java中A的静态方法 } } A.foo() class B { companion object Comp{ //注意companion关键字 fun foo() = 2 //相当于java中A的静态方法 } } B.Comp.foo() == B.foo() //在java中访问 A.Companion.foo() B.Comp.foo() //对伴生对象扩展 fun A.Companion.func() = "" fun B.Comp.func() = ""
- kotlin写法的匿名内部类
var count = 0
window.addMouseListener(
object: MouseAdapter() {
override fun mouseClicked(e : MouseEvent){ count++ } //可以直接访问外部变量
override fun mouseEntered(e : MouseEvent){...}
}
)