一、核心区别速览
| 特性 |
普通类(继承) |
抽象类 |
接口 |
| 实例化 |
可以直接实例化 |
不能实例化 |
不能实例化 |
| 构造函数 |
可以有主/次构造函数 |
可以有构造函数 |
没有构造函数 |
| 状态存储 |
✅ 可以有属性+幕后字段 |
✅ 可以有属性+幕后字段 |
❌ 属性无幕后字段(只能 val/getter) |
| 方法实现 |
必须全部实现 |
可以混合(抽象+具体) |
可以混合(抽象+默认实现) |
| 多继承/实现 |
单继承 |
单继承 |
多实现 |
| 访问修饰符 |
全部支持 |
全部支持 |
仅 public(默认) |
open 要求 |
需要 open 才能被继承 |
默认 open(抽象方法) |
默认 open(无需标注) |
| 设计目的 |
"是什么"(Is-A 关系) |
"模板/骨架" |
"能做什么"(Can-Do 关系) |
二、继承(普通类):代码复用 + 扩展
适用场景
- 明确的 Is-A 关系(子类确实是父类的一种)
- 父类有完整实现,子类只需部分修改
- 需要共享状态(属性值)
实战示例:员工系统
// 父类:必须 open
open class Employee(
val id: Int,
open val name: String, // 允许子类重写
open var salary: Double
) {
// 具体实现方法(可被子类重写)
open fun calculateBonus(): Double {
return salary * 0.05 // 基础奖金 5%
}
fun showInfo() {
println("ID: $id, Name: $name, Salary: $salary")
}
}
// 子类:经理
class Manager(
id: Int,
name: String,
salary: Double,
val teamSize: Int
) : Employee(id, name, salary) {
override fun calculateBonus(): Double {
return salary * 0.15 + teamSize * 100 // 经理奖金更高
}
// 新增特有方法
fun conductMeeting() {
println("$name 正在主持会议")
}
}
// 使用
fun main() {
val emp = Employee(1, "张三", 8000.0)
val mgr = Manager(2, "李四", 15000.0, 5)
println(emp.calculateBonus()) // 400.0
println(mgr.calculateBonus()) // 2750.0
mgr.conductMeeting()
}
三、抽象类:提供模板骨架
适用场景
- 多个子类有共同的结构和行为,但部分实现需要子类自行完成
- 需要共享状态(属性)和基础逻辑
- 提供模板方法模式(定义算法骨架)
实战示例:支付系统
abstract class PaymentProcessor(val merchantId: String) {
// 可继承的属性(带默认值)
protected var retryCount: Int = 3
// 抽象属性:必须由子类实现
abstract val supportedCurrency: String
// 抽象方法:子类必须实现
abstract fun processPayment(amount: Double): Boolean
// 具体方法:提供通用逻辑
fun validateAmount(amount: Double): Boolean {
return amount > 0
}
// 模板方法:定义算法骨架
fun executePayment(amount: Double): String {
if (!validateAmount(amount)) {
return "金额无效"
}
println("[$merchantId] 开始处理支付...")
var success = false
var attempts = 0
while (attempts < retryCount && !success) {
attempts++
success = processPayment(amount)
if (!success) {
println("支付失败,重试第 $attempts 次")
}
}
return if (success) "支付成功" else "支付失败"
}
}
// 具体子类1:支付宝
class AlipayProcessor(merchantId: String) : PaymentProcessor(merchantId) {
override val supportedCurrency: String = "CNY"
override fun processPayment(amount: Double): Boolean {
// 模拟支付宝支付逻辑
println("使用支付宝支付 $amount CNY")
return true // 模拟成功
}
}
// 具体子类2:PayPal
class PayPalProcessor(merchantId: String) : PaymentProcessor(merchantId) {
override val supportedCurrency: String = "USD"
init {
retryCount = 5 // PayPal 重试次数更多
}
override fun processPayment(amount: Double): Boolean {
println("使用 PayPal 支付 $amount USD")
return amount <= 10000 // 模拟限额
}
}
fun main() {
val alipay = AlipayProcessor("M001")
println(alipay.executePayment(500.0)) // 成功
val paypal = PayPalProcessor("M002")
println(paypal.executePayment(20000.0)) // 失败(超限)
}
四、接口:定义行为契约
适用场景
-
能力声明:"这个类能做某事"(Can-Do 关系)
- 无关的类提供相同行为(如:可序列化、可比较)
- 需要多实现(组合多种能力)
- 定义回调接口或监听器
实战示例:多媒体系统
// 接口1:播放能力
interface Playable {
val duration: Int // 抽象属性
fun play()
// 默认方法
fun pause() {
println("暂停播放")
}
}
// 接口2:下载能力
interface Downloadable {
val url: String
fun download() {
println("从 $url 下载中...")
}
}
// 接口3:广告展示
interface AdSupported {
fun showAd() {
println("展示 30 秒广告")
}
}
// 具体类1:音乐(实现多个接口)
class Music(
override val duration: Int,
override val url: String,
val artist: String
) : Playable, Downloadable {
override fun play() {
println("播放 $artist 的音乐,时长 $duration 秒")
}
// 可以重写默认方法
override fun download() {
println("下载音乐 $artist 的高清版")
}
}
// 具体类2:视频(带广告)
class Video(
override val duration: Int,
override val url: String,
val resolution: String
) : Playable, Downloadable, AdSupported {
override fun play() {
showAd() // 播放前先看广告
println("播放 $resolution 视频,时长 $duration 秒")
}
}
// 接口委托示例
interface Logger {
fun log(message: String)
}
class ConsoleLogger : Logger {
override fun log(message: String) {
println("[${System.currentTimeMillis()}] $message")
}
}
// 使用委托简化实现
class UserService(private val userId: Int) : Logger by ConsoleLogger() {
fun doSomething() {
log("用户 $userId 执行操作") // 自动委托给 ConsoleLogger
}
}
五、三者的协同使用(经典架构)
在实际项目中,三者通常结合使用:
// 1. 接口定义核心能力
interface DataSource {
fun fetchData(): List<String>
fun saveData(data: List<String>)
}
// 2. 抽象类提供通用模板
abstract class BaseDataSource(private val sourceName: String) : DataSource {
abstract val maxRetry: Int
// 模板方法
override fun fetchData(): List<String> {
println("从 $sourceName 获取数据(重试 $maxRetry 次)")
return performFetch()
}
protected abstract fun performFetch(): List<String>
// 具体实现
override fun saveData(data: List<String>) {
println("保存数据到 $sourceName: ${data.size} 条")
}
}
// 3. 具体实现继承抽象类 + 额外接口
interface Cacheable {
fun clearCache()
}
class DatabaseDataSource(
private val dbUrl: String
) : BaseDataSource("Database"), Cacheable {
override val maxRetry: Int = 3
override fun performFetch(): List<String> {
// 模拟数据库查询
return listOf("数据1", "数据2", "数据3")
}
override fun clearCache() {
println("清除数据库缓存")
}
}
class ApiDataSource(
private val endpoint: String
) : BaseDataSource("API"), Cacheable {
override val maxRetry: Int = 5
override fun performFetch(): List<String> {
// 模拟 API 调用
return listOf("API 数据")
}
override fun clearCache() {
println("清除 API 缓存")
}
}
六、实战选择决策树
需要定义一种类型?
│
├─ 需要实例化吗?
│ ├─ 是 → 普通类(继承或 final)
│ └─ 否 ↓
│
├─ 需要构造函数或存储状态吗?
│ ├─ 是 → 抽象类
│ └─ 否 → 接口
│
├─ 需要多继承/多能力组合吗?
│ ├─ 是 → 接口(多实现)
│ └─ 否 → 抽象类(单继承)
│
├─ 需要提供部分默认实现 + 部分抽象吗?
│ ├─ 是 → 都可以(抽象类偏重状态,接口偏重行为)
│ └─ 否 → 接口更轻量
具体建议(Android/Kotlin 常见场景)
| 场景 |
推荐方案 |
| Activity/Fragment 基类 |
抽象类(需要状态和生命周期) |
| 点击监听器 |
接口(函数式接口可用 Lambda 替代) |
| RecyclerView Adapter 基类 |
抽象类(模板方法) |
| 网络请求的多种实现(Mock/Real) |
接口(依赖倒置) |
| 数据模型(POJO) |
普通类(最好 data class) |
| 工具类 Utils |
普通类 + object 单例 |
七、重要限制和注意事项
1. 继承的脆弱性(Fragile Base Class)
// ❌ 不好:深度继承
open class A { open fun foo() = 1 }
class B : A() { override fun foo() = super.foo() + 1 }
class C : B() { override fun foo() = super.foo() + 1 } // 依赖太多
// ✅ 推荐:使用组合 + 接口
interface Fooable { fun foo(): Int }
class FooImpl : Fooable { override fun foo() = 1 }
class MyClass(private val fooable: Fooable) : Fooable by fooable
2. open vs final vs abstract
open class Parent {
open fun canOverride() {} // 可重写
fun cannotOverride() {} // 默认 final,不可重写
}
abstract class AbstractChild : Parent() {
abstract fun mustImplement() // 抽象方法,子类必须实现
}
3. 接口属性注意事项
interface BadInterface {
// ❌ 编译错误:接口属性不能有幕后字段
// var counter: Int = 0
// ✅ 可以这样写(但每次调用都重新计算)
val time: String
get() = System.currentTimeMillis().toString()
}
八、综合实战:设计一个支付系统
// ========== 接口层 ==========
interface Payable {
fun pay(amount: Double): Boolean
fun refund(amount: Double): Boolean
}
interface Verifiable {
fun verify(): Boolean
}
// ========== 抽象层 ==========
abstract class BasePayment(
val accountId: String,
protected var balance: Double
) : Payable, Verifiable {
abstract val feeRate: Double // 手续费率
override fun verify(): Boolean {
println("验证账户 $accountId")
return accountId.isNotEmpty()
}
override fun pay(amount: Double): Boolean {
if (!verify()) return false
val totalAmount = amount * (1 + feeRate)
if (balance < totalAmount) {
println("余额不足")
return false
}
balance -= totalAmount
println("支付 $amount, 手续费 ${amount * feeRate}, 余额 $balance")
return true
}
override fun refund(amount: Double): Boolean {
balance += amount
println("退款 $amount, 新余额 $balance")
return true
}
}
// ========== 实现层 ==========
class WeChatPayment(
accountId: String,
balance: Double,
private val weChatId: String
) : BasePayment(accountId, balance) {
override val feeRate: Double = 0.001 // 微信费率 0.1%
override fun verify(): Boolean {
return super.verify() && weChatId.startsWith("wx_")
}
}
class CreditCardPayment(
accountId: String,
balance: Double,
private val cardNumber: String
) : BasePayment(accountId, balance) {
override val feeRate: Double = 0.006 // 信用卡费率 0.6%
override fun pay(amount: Double): Boolean {
println("信用卡预授权 $amount")
return super.pay(amount)
}
}
// ========== 使用 ==========
fun main() {
val wechat = WeChatPayment("wx_001", 1000.0, "wx_123")
wechat.pay(100.0) // 支付 100, 手续费 0.1, 余额 899.9
val credit = CreditCardPayment("cc_001", 5000.0, "1234-5678")
credit.pay(500.0) // 信用卡预授权 500, 手续费 3.0, 余额 4497.0
}