Skip to content

类、属性与接口

源:Kotlin 类系统参考

Kotlin 的类系统极度精简。它通过主构造函数属性代理默认 final 等特性,强制引导开发者编写更安全的代码。

构造体系

Kotlin 区分 主构造函数 (Primary)次构造函数 (Secondary)

kotlin
// 1. 直接在类头定义参数
// 2. var/val 参数自动成为属性
class User(val id: Int, var name: String) {
    
    // 初始化块 (Init Block):配合主构造函数使用
    init {
        require(id > 0) { "Invalid ID" }
        println("User $name created")
    }
}
kotlin
class View : View {
    // 必须委托给主构造函数 (如果存在) 或其他次构造函数
    constructor(ctx: Context) : super(ctx)
    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
}

属性 (Properties)

Kotlin 的属性不仅仅是字段,它自带 Getter/Setter 钩子。

幕后字段 (Backing Field)

当你自定义 Setter 时,必须使用 field 关键字来访问实际存储值的变量。

kotlin
var counter = 0
    set(value) {
        if (value >= 0) {
            // ❌ counter = value (死循环!)
            field = value // ✅ 正确
        }
    }

继承与多态

默认 Final

Kotlin 类默认是 final 的(不可继承)。要允许继承,必须添加 open 关键字。

kotlin
open class Base {
    open fun v() {}
    fun nv() {} // 默认为 final,不可覆盖
}

class Derived : Base() {
    override fun v() {}
}

super 歧义处理

当继承的多个父类(如接口)有同名默认实现时,必须显式指定 super<T>

kotlin
interface A { fun foo() = print("A") }
interface B { fun foo() = print("B") }

class C : A, B {
    override fun foo() {
        super<A>.foo() // 调用 A.foo()
        super<B>.foo() // 调用 B.foo()
    }
}

嵌套类 vs 内部类

这是 Android 开发中 内存泄漏 的高发区。

关键字对应 Java持有外部引用?风险
无 (默认)static class安全
innerclass高风险 (可能导致 Activity 泄漏)

内存泄漏警告

在 Activity/Fragment 中使用 inner class (如 Handler, Adapter) 时,如果该内部类的生命周期长于外部类(例如被异步线程持有),会导致 Activity 无法被 GC 回收。 建议:默认使用嵌套类(不加 inner)。

kotlin
class Outer {
    private val bar: Int = 1
    
    // 嵌套类:无法访问 bar
    class Nested {
        fun foo() = 2
    }
    
    // 内部类:可以访问 bar
    inner class Inner {
        fun foo() = bar
    }
}

函数式接口 (Functional Interface)

如果接口只有一个抽象方法,标记为 fun interface 可支持 SAM 转换(直接传入 Lambda)。

kotlin
fun interface ClickListener {
    fun onClick(pos: Int)
}

// 使用
val listener = ClickListener { pos -> println("Clicked $pos") }