Kotlin 中的继承与实现

继承:子类(Subclass)继承父类(Superclass)的属性和方法,用于代码复用和多态,关键词是 : 父类()(只能有一个)。

实现:类实现接口(Interface)的抽象方法,用于定义行为规范,关键词是: 接口(可多个)。

Kotlin 对继承做了严格限制:所有类默认是 final 的(不可继承),必须显式用 open 修饰才能被继承;接口默认是 open 的且接口中的方法默认是 open/abstract 的。

1 继承

1.1 基础语法
kotlin 复制代码
// 1. 父类:必须用 open 修饰才能被继承
open class Animal(
    val name: String,
    val age: Int
) {
    // 父类方法:默认 final,用 open 修饰才能被重写
    open fun makeSound() {
        println("$name 发出声音")
    }

    open fun eat() {
        println("$name 吃东西")
    }
}

// 2. 子类:继承 Animal,用 : 父类(构造参数)
class Dog(name: String, age: Int, val breed: String) : Animal(name, age) {
    // 重写父类方法:必须用 override 修饰
    override fun makeSound() {
        println("$name ($breed) 汪汪叫")
    }
}

// 3. 使用
fun main() {
    val dog = Dog("旺财", 3, "哈士奇")
    dog.makeSound()     // 旺财 (哈士奇) 汪汪叫
    dog.eat()           // 旺财 吃东西
}
1.2 继承的关键规则
  • 构造函数调用: 子类必须在声明处或主构造函数中调用父类的构造函数(Animal(name, age));
  • 重写限制:
    • 父类方法/属性必须加 open 才能被重写;
    • 子类重写必须加 override(不可省略);
    • 重写后的方法默认是 open 的,若想禁止子类再重写,加 final
  • 属性重写: 不仅方法,属性也能重写(需父类属性加 open);
  • 单继承限制: Kotlin 和 Java 一样,一个类只能继承一个父类,避免多继承的菱形问题;

代码示例:

kotlin 复制代码
// 禁止子类再重写
final override fun makeSound() {
  
}

// 属性重写
open class Animal {
    open val legCount: Int = 4
}

class Bird : Animal() {
    override val legCount: Int = 2 // 重写属性值
}

2 实现

2.1 基础实现语法

接口定义行为规范,类实现接口时必须实现其所有抽象方法:

kotlin 复制代码
interface Runnable {
    // 抽象方法(默认 abstract,无需显式声明)
    fun run()

    fun stop() {
        println("停止运行")
    }
}

interface Swimmable {
    fun swim()
}

class Fish : Runnable, Swimmable {
    override fun run() {
        println("鱼靠鳍游动")
    }

    override fun swim() {
        println("鱼在水里游")
    }

    override fun stop() {
        println("鱼静止在水中")
    }

}

// 3. 使用
fun main() {
    val fish = Fish()
    fish.run()      // 输出:鱼靠鱼鳍游动
    fish.swim()     // 鱼在水里游
    fish.stop()     // 鱼静止在水中
}
2.2 接口的关键规则
  • 接口不能有构造函数: 接口无法实例化,只能被类实现;
  • 接口属性: 接口中可声明属性,但只能是抽象的,或提供默认 getter;
  • 多实现冲突: 若实现多个接口且接口有同名默认方法,必须显式重写解决冲突;

代码示例:

kotlin 复制代码
interface Flyable {
    val maxSpeed: Int // 抽象属性,实现类必须重写
    val minSpeed: Int get() = 0 // 默认 getter,实现类可选择重写
}

class Eagle : Flyable {
    override val maxSpeed: Int = 100 // 必须重写抽象属性
    // minSpeed 使用默认值 0,无需重写
}

interface A {
    fun doSomething() = println("A")
}

interface B {
    fun doSomething() = println("B")
}

class C : A, B {
    override fun doSomething() {
        // 显式指定使用哪个接口的实现
        super<A>.doSomething()
        super<B>.doSomething()
        // 或自定义逻辑
        println("C")
    }
}

3 继承 + 实现 混合使用

实际开发中,类通常既继承父类,又实现多个接口:

kotlin 复制代码
// 父类
open class Vehicle(val brand: String) {
    open fun drive() {
        println("$brand 行驶中")
    }
}

// 接口 1
interface Electric {
    fun charge() = println("充电中")
}

// 接口 2
interface Autopilot {
    fun autoDrive()
}

// 子类:继承 Vehicle + 实现 Electric、Autopilot
class Tesla(brand: String) : Vehicle(brand), Electric, Autopilot {

    // 重写父类方法
    override fun drive() {
        println("$brand 电动行驶中")
    }

    // 实现接口的抽象方法
    override fun autoDrive() {
        println("$brand 自动驾驶中")
    }

    // 可选:重写接口默认方法
    override fun charge() {
        println("$brand 超充中(1小时充满)")
    }


}
// 3. 使用
fun main() {
    val tesla = Tesla("特斯拉 Model Y")
    tesla.drive()       // 特斯拉 Model Y 电动行驶中
    tesla.charge()      // 特斯拉 Model Y 超充中(1小时充满)
    tesla.autoDrive()   // 特斯拉 Model Y 自动驾驶中
}

4 抽象类 + 接口 组合

抽象类(abstract class)是"半实现"的类(可包含抽象方法和具体方法),接口是"纯规范":

kotlin 复制代码
// 抽象类:有抽象方法 + 具体方法
abstract class Shape {
    abstract fun calculateAre(): Double // 抽象方法,子类必须实现

    fun printInto() {
        println("面积 ${calculateAre()}")
    }
}

// 接口:定义额外行为
interface Drawable {
    fun draw()
}

// 子类:继承抽象类 + 实现接口
class Circle(val radius: Double) : Shape(), Drawable {
    override fun calculateAre(): Double {
        return Math.PI * radius * radius
    }

    override fun draw() {
        println("绘制圆形,半径: $radius")
    }
}

fun main() {
    val circle = Circle(5.0)
    circle.draw()  // 绘制圆形,半径: 5.0
    circle.printInto() // 面积 78.53981633974483
}
相关推荐
liang_jy7 小时前
Android SparseArray
android·源码
liang_jy8 小时前
Activity 启动流程扩展篇(一)—— startActivityInner 任务决策全解析
android·源码
NPE~9 小时前
[App逆向]脱壳实战
android·教程·逆向·android逆向·逆向分析
木易 士心9 小时前
别再只会用 drawCircle 了!一文搞懂 Android Canvas 底层机制
android
AtOR CUES10 小时前
MySQL——表操作及查询
android·mysql·adb
怣疯knight11 小时前
安卓App无法增加自定义图片作为图标功能
android
jinanwuhuaguo13 小时前
OpenClaw联邦之心——从孤岛记忆到硅基集体潜意识的拓扑学革命(第二十三篇)
android·人工智能·kotlin·拓扑学·openclaw
Gary Studio14 小时前
安卓HAL C++基础-命名域
android
诸神黄昏EX15 小时前
Android Google XTS
android
eSsO KERF15 小时前
MySQL Workbench菜单汉化为中文
android·数据库·mysql