电脑学堂
第二套高阶模板 · 更大气的阅读体验

Kotlin接口与抽象类:别再傻傻分不清

发布时间:2026-01-02 00:50:47 阅读:14 次

接口和抽象,到底有啥不一样

Kotlin的时候,经常遇到需要定义一些通用行为的场景。比如你正在开发一个智能家居系统,灯、空调、窗帘都得能“开关”。这时候你会想:用接口还是抽象类?很多人一开始都搞混,其实它们的定位差得挺远。

接口:定义“能做什么”

接口(interface)就像一份契约,它不关心你怎么实现,只规定你能提供哪些功能。比如所有能开关的设备,都可以实现一个叫Switchable的接口。

interface Switchable {
    fun turnOn()
    fun turnOff()
}

然后你的台灯类就可以实现它:

class DeskLamp : Switchable {
    override fun turnOn() {
        println("台灯亮了")
    }

    override fun turnOff() {
        println("台灯关了")
    }
}

接口最大的好处是支持多实现。比如窗帘除了能开关,还可能要定时启动,那它可以同时实现Switchable和TimerTask。

抽象类:共享“怎么做”

抽象类(abstract class)更像一个半成品模板,它不仅能定义方法,还能提供部分实现。比如你发现多个设备都有“延时关闭”这种共用逻辑,那就适合放在抽象类里。

abstract class SmartDevice {
    abstract fun turnOn()
    abstract fun turnOff()

    fun delayOff(seconds: Int) {
        println("$seconds秒后自动关闭")
        // 模拟延时逻辑
    }
}

子类继承后,不仅得实现开关方法,还能直接用delayOff这个现成功能。

class CeilingFan : SmartDevice() {
    override fun turnOn() {
        println("吊扇启动")
    }

    override fun turnOff() {
        println("吊扇停止")
    }
}

选择的关键:是“能做什么”还是“怎么做的”

如果你只是想统一调用方式,比如所有可开关设备都能被遥控器控制,那就用接口。如果多个类之间有共用的状态或行为逻辑,比如都带延时、都记录日志,那抽象类更合适。

Kotlin还允许接口有默认实现,这让两者的界限看起来模糊了些。比如:

interface Loggable {
    fun log(message: String) {
        println("[LOG] $message")
    }
}

这样任何实现Loggable的类都自动拥有了log方法,不用强制重写。但这依然不能替代抽象类,因为接口不能保存状态,比如你没法在接口里定义一个计数器变量。

实际开发中,大多数情况优先选接口。它更灵活,也符合Kotlin鼓励组合优于继承的设计哲学。只有当你确实需要共享代码和状态时,才考虑抽象类。