Kotlin: Kotlin继承与接口详解

最后更新:2026-08-26

Kotlin 的继承模型比 Java 更安全:类默认 final 不可继承,方法默认不可重写——Charlie 必须显式声明 才开放继承,编译器守护多态安全。

1. 你将学到


2. 一个架构师的真实故事

(1) 痛点:意外重写导致生产事故

Bob 继承了 类创建 ,无意中重写了 方法,导致 500 笔特殊订单金额计算错误,财务部门紧急报警。

(2) Kotlin 的编译期守护

KOTLIN
// Java: override annotation is optional - silent override possible
class SpecialOrder extends Order {
    double calculateTotal() { ... }  // Silently overrides!
}

// Kotlin: override is MANDATORY - compiler catches mistakes
open class Order {
    open fun calculateTotal(): Double = ...
}
class SpecialOrder : Order() {
    override fun calculateTotal(): Double = ...  // Must declare override
}

强制标注 + 类默认 final = 编译器守护继承安全,Bob 再也不会意外重写。


3. 开放继承模型

(1) 类默认 final

KOTLIN
// Default: class is final (cannot be inherited)
class Order(val id: String)  // Cannot be extended

// Open: explicitly allow inheritance
open class Order(val id: String) {
    // Methods are also final by default
    fun process() { }  // Cannot be overridden

    // Open method: explicitly allow override
    open fun calculateTotal(): Double = 0.0
}

// Abstract: must be inherited, cannot be instantiated
abstract class BaseOrder(val id: String) {
    // Abstract method: must be implemented by subclass
    abstract fun calculateTotal(): Double

    // Concrete method in abstract class
    fun getId(): String = id
}

(2) 继承修饰符层级

修饰符 方法 能实例化 能继承 能重写
默认(final)
✅(必须) ✅(必须)

(3) Java vs Kotlin 继承对比

维度 Java Kotlin
类默认 可继承 final(不可继承)
方法默认 可重写 final(不可重写)
重写标注 (可选) (强制)
开放继承 无需声明 显式声明
设计哲学 "默认开放" "默认封闭"

4. 接口与默认实现

(1) 接口定义

KOTLIN
interface Discountable {
    // Abstract method
    fun discountRate(): Double

    // Default implementation
    fun applyDiscount(total: Double): Double {
        return total * (1.0 - discountRate())
    }
}

interface Trackable {
    val trackingCode: String?  // Abstract property

    fun track(): String = trackingCode?.let { "Tracking: $it" } ?: "Not shipped"
}

// Implement multiple interfaces
class PremiumOrder(
    val id: String,
    val total: Double,
    override val trackingCode: String?
) : Discountable, Trackable {
    override fun discountRate() = 0.15  // 15% discount
}

(2) 接口 vs 抽象类

维度 接口 抽象类
构造器
状态 无(只有抽象属性) 有(具体属性)
多继承 支持(可实现多个) 不支持(只能继承一个)
默认实现 Kotlin 支持 支持
适用场景 行为契约 共享状态 + 行为

5. override 强制标注

(1) 基本用法

KOTLIN
open class Order(val id: String, var status: String) {
    open fun summary(): String = "Order $id: $status"
}

class BulkOrder(id: String, status: String, val minQuantity: Int) : Order(id, status) {
    // MUST use override keyword
    override fun summary(): String = "Bulk $id: $status (min: $minQuantity)"
}

(2) 防止进一步重写

KOTLIN
open class Order {
    open fun process() { }
}

class SpecialOrder : Order() {
    // Prevent further override in subclasses
    final override fun process() { }
}

6. 多继承冲突解决

(1) 钻石继承问题

KOTLIN
interface A {
    fun hello() = "A"
}

interface B {
    fun hello() = "B"
}

// Diamond: C inherits hello() from both A and B
class C : A, B {
    // MUST override to resolve conflict
    override fun hello(): String {
        // Explicitly choose which parent's implementation
        return super`<A>`.hello()  // Choose A's implementation
    }
}

(2) 冲突解决策略

KOTLIN
class D : A, B {
    override fun hello(): String {
        // Strategy 1: Pick one parent
        return super`<B>`.hello()

        // Strategy 2: Combine both
        // return "${super`<A>`.hello()} + ${super`<B>`.hello()}"

        // Strategy 3: Custom implementation
        // return "D"
    }
}

(3) 冲突解决方式对比

策略 语法 适用场景
选择父类 A <A> A 的实现更合适
选择父类 B <B> B 的实现更合适
组合两者 <A>``<B> 需要两者行为
全新实现 自定义代码 都不合适

7. 继承体系图

100%
classDiagram
    class Order {
        +val id: String
        +var status: String
        +open fun summary(): String
        +open fun calculateTotal(): Double
    }
    class BulkOrder {
        +val minQuantity: Int
        +override fun calculateTotal(): Double
    }
    class PriorityOrder {
        +val priority: String
        +override fun summary(): String
    }
    class Discountable {
        <<interface>>
        +fun discountRate(): Double
        +fun applyDiscount(total: Double): Double
    }
    class Trackable {
        <<interface>>
        +val trackingCode: String?
        +fun track(): String
    }
    Order <|-- BulkOrder
    Order <|-- PriorityOrder
    BulkOrder ..|> Discountable
    PriorityOrder ..|> Trackable
    PriorityOrder ..|> Discountable

8. 完整示例:OrderProcessor 继承体系

KOTLIN
// ============================================
// OrderProcessor - Inheritance Hierarchy
// Feature: Order / BulkOrder / PriorityOrder
// ============================================

interface Discountable {
    fun discountRate(): Double
    fun applyDiscount(total: Double): Double = total * (1.0 - discountRate())
}

interface Trackable {
    val trackingCode: String?
    fun track(): String = trackingCode?.let { "Tracking: $it" } ?: "Not shipped yet"
}

open class Order(val id: String, var status: String, val total: Double) {
    init {
        require(total >= 0) { "Total must be non-negative" }
    }

    open fun summary(): String = "Order $id | \$$total USD | $status"
    open fun calculateFinal(): Double = total
}

class BulkOrder(
    id: String,
    status: String,
    total: Double,
    val minQuantity: Int
) : Order(id, status, total), Discountable {

    override fun discountRate() = 0.10  // 10% bulk discount

    override fun calculateFinal(): Double = applyDiscount(total)

    override fun summary(): String =
        "${super.summary()} | Bulk (min: $minQuantity) | Final: \$${calculateFinal()} USD"
}

class PriorityOrder(
    id: String,
    status: String,
    total: Double,
    val priority: String,
    override val trackingCode: String?
) : Order(id, status, total), Discountable, Trackable {

    override fun discountRate() = when (priority) {
        "VIP" -> 0.20
        "GOLD" -> 0.15
        else -> 0.05
    }

    override fun calculateFinal(): Double = applyDiscount(total)

    override fun summary(): String =
        "${super.summary()} | Priority: $priority | ${track()} | Final: \$${calculateFinal()} USD"
}

fun main() {
    val orders = listOf(
        Order("ORD-001", "CONFIRMED", 299.99),
        BulkOrder("ORD-002", "CONFIRMED", 5_000.00, 100),
        PriorityOrder("ORD-003", "SHIPPED", 15_000.00, "VIP", "TRK-XYZ789"),
        PriorityOrder("ORD-004", "PENDING", 2_500.00, "GOLD", null)
    )

    println("=== Order Summary ===")
    orders.forEach { println(it.summary()) }

    val totalSavings = orders
        .filterIsInstance`<Discountable>`()
        .sumOf { it.applyDiscount((it as Order).total) - (it as Order).calculateFinal() }

    println("\nTotal savings from discounts: \$$totalSavings USD")
}

输出:

TEXT 📖 仅展示
=== Order Summary ===
Order ORD-001 | $299.99 USD | CONFIRMED
Order ORD-002 | $5000.0 USD | CONFIRMED | Bulk (min: 100) | Final: $4500.0 USD
Order ORD-003 | $15000.0 USD | SHIPPED | Priority: VIP | Tracking: TRK-XYZ789 | Final: $12000.0 USD
Order ORD-004 | $2500.0 USD | PENDING | Priority: GOLD | Not shipped yet | Final: $2125.0 USD

Total savings from discounts: $3475.0 USD

❓ 常见问题

Q 为什么 Kotlin 类默认 final?
A Effective Java 建议"要么为继承而设计并文档化,要么禁止继承"。Kotlin 采纳这个建议,默认禁止继承,用 显式开放。
Q 接口可以有构造器吗?
A 不能。接口没有构造器,不能保存状态。需要状态共享请用抽象类。
Q 一个类可以实现多个接口的默认方法冲突吗?
A 如果两个接口有同名同签名的默认方法,子类必须 override 该方法解决冲突,用 <InterfaceName> 选择实现。
Q override 可以省略吗?
A 不能。Kotlin 强制要求 override 关键字,省略会导致编译错误。这是防止意外重写的关键安全机制。
Q 抽象类的 open 方法需要写 open 吗?
A 不需要。抽象类的抽象方法默认可重写(必须重写),非抽象的 open 方法仍需 标记。
Q Kotlin 有类似 Java 的 调用吗?
A 有。子类构造器用 调用父类构造器,方法中用 调用父类实现,接口用 <Interface>

📖 小节


📝 作业

  1. 基础题(难度⭐):定义一个 和 继承它,重写 方法。提示:
  2. 进阶题(难度⭐⭐):创建 和 两个接口,让 同时实现两个接口,解决同名方法冲突。提示:<Discountable>
  3. 挑战题(难度⭐⭐⭐):设计完整的订单继承体系: → / ,各自实现不同的折扣和物流策略。提示:结合接口和抽象类

← 上一课 | 下一课 →

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏