Kotlin 集成、接口、抽象类


一、核心区别速览

特性 普通类(继承) 抽象类 接口
实例化 可以直接实例化 不能实例化 不能实例化
构造函数 可以有主/次构造函数 可以有构造函数 没有构造函数
状态存储 ✅ 可以有属性+幕后字段 ✅ 可以有属性+幕后字段 ❌ 属性无幕后字段(只能 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
}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容