Kotlin: Kotlin继承与接口详解
最后更新:2026-08-26
Kotlin 的继承模型比 Java 更安全:类默认 final 不可继承,方法默认不可重写——Charlie 必须显式声明 才开放继承,编译器守护多态安全。
1. 你将学到
- / :类默认 final,需显式开放
- 接口默认实现
- 强制标注
- 多继承冲突解决:
<ParentA> - Charlie 实战:BulkOrder / PriorityOrder 继承体系
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. 继承体系图
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>。📖 小节
- Kotlin 类默认 final,必须 才能继承——默认封闭,显式开放
- 类不可实例化,抽象方法必须由子类实现
- 接口支持默认实现和抽象属性,可多实现
- 强制标注防止意外重写,编译器守护多态安全
- 多继承冲突用
<Interface>显式选择 - 接口用于行为契约(无状态),抽象类用于共享状态+行为
📝 作业
- 基础题(难度⭐):定义一个 和 继承它,重写 方法。提示:
- 进阶题(难度⭐⭐):创建 和 两个接口,让 同时实现两个接口,解决同名方法冲突。提示:
<Discountable> - 挑战题(难度⭐⭐⭐):设计完整的订单继承体系: → / ,各自实现不同的折扣和物流策略。提示:结合接口和抽象类