2-6-1 快速掌握Kotlin-语言的接口定义

Kotlin 接口定义

Kotlin 接口是一种强大的抽象机制,它允许定义方法、属性、默认实现,并且支持多继承。以下是 Kotlin 接口的完整指南:

1. 基本接口定义

简单接口

kotlin 复制代码
// 定义接口
interface Drawable {
    fun draw()  // 抽象方法
}

// 实现接口
class Circle : Drawable {
    override fun draw() {
        println("绘制圆形")
    }
}

带属性的接口

kotlin 复制代码
interface Shape {
    val name: String  // 抽象属性
    
    val description: String
        get() = "这是一个形状"  // 带 getter 的属性
}

class Square : Shape {
    override val name: String = "正方形"
    
    // 可以重写 description 属性
    override val description: String
        get() = "这是一个四边相等的形状"
}

2. 接口中的方法

抽象方法和默认实现

kotlin 复制代码
interface Vehicle {
    // 抽象方法(必须被实现)
    fun start()
    
    // 带默认实现的方法(可选重写)
    fun stop() {
        println("车辆停止")
    }
    
    // 也可以有具体实现的方法体
    fun honk() = println("嘟嘟!")
}

class Car : Vehicle {
    override fun start() {
        println("汽车启动")
    }
    
    // 可以选择重写 stop(),也可以使用默认实现
    override fun stop() {
        println("汽车紧急制动")
    }
    
    // 不重写 honk(),使用接口中的默认实现
}

私有方法(Kotlin 1.7+)

kotlin 复制代码
interface DatabaseAccess {
    fun save(data: String) {
        validate(data)
        println("保存数据: $data")
    }
    
    private fun validate(data: String) {  // 接口中的私有方法
        require(data.isNotBlank()) { "数据不能为空" }
    }
}

3. 接口中的属性

各种属性类型

kotlin 复制代码
interface User {
    // 抽象属性(必须被实现)
    val username: String
    
    // 带 getter 的属性
    val displayName: String
        get() = username.uppercase()
    
    // 可变属性
    var email: String
    
    // 常量(使用伴生对象)
    companion object {
        const val MIN_USERNAME_LENGTH = 3
    }
}

class RegularUser(override val username: String) : User {
    override var email: String = ""
    
    // 可以重写 displayName
    override val displayName: String
        get() = "用户: ${username.lowercase()}"
}

4. 接口继承

接口继承接口

kotlin 复制代码
interface Clickable {
    fun click()
}

interface Focusable : Clickable {
    fun focus()
    fun showOff() = println("我是可聚焦的!")
}

class Button : Focusable {
    override fun click() {
        println("按钮被点击")
    }
    
    override fun focus() {
        println("按钮获得焦点")
    }
    
    // 可以选择重写 showOff() 或不重写
}

多接口继承

kotlin 复制代码
interface A {
    fun foo() = println("A.foo")
}

interface B {
    fun foo() = println("B.foo")
    fun bar() = println("B.bar")
}

class C : A, B {
    // 必须重写 foo() 来解决冲突
    override fun foo() {
        // 调用特定父接口的实现
        super<A>.foo()
        super<B>.foo()
        println("C.foo")
    }
    
    // 不需要重写 bar(),因为只有一个实现
}

5. 函数式接口(SAM接口)

单抽象方法接口

kotlin 复制代码
// 使用 fun interface 声明(Kotlin 1.4+)
fun interface StringProcessor {
    fun process(input: String): String
}

// 传统方式
interface OnClickListener {
    fun onClick(view: View)
}

// 使用 lambda 表达式实现
val processor = StringProcessor { it.uppercase() }
val listener = OnClickListener { println("点击了 $it") }

// 在函数参数中使用
fun setOnClickListener(listener: OnClickListener) {
    // ...
}

// 调用时可以传递 lambda
setOnClickListener { view -> println("点击") }

Java 函数式接口互操作

kotlin 复制代码
// Java 中的函数式接口
// @FunctionalInterface
// public interface Runnable { void run(); }

val runnable = Runnable { println("在后台运行") }
Thread(runnable).start()

// 或者直接使用
Thread { println("简洁写法") }.start()

6. 接口与抽象类的比较

kotlin 复制代码
// 接口
interface AnimalInterface {
    val name: String
    fun makeSound()
    
    fun eat() {  // 可以有默认实现
        println("$name 正在进食")
    }
}

// 抽象类
abstract class AnimalAbstract {
    abstract val name: String
    abstract fun makeSound()
    
    open fun eat() {  // 需要 open 关键字
        println("$name 正在进食")
    }
    
    // 抽象类可以有状态
    var age: Int = 0
    
    // 可以有构造函数
    constructor(name: String)
}

// 实现差异
class DogInterface : AnimalInterface {
    override val name: String = "狗狗"
    override fun makeSound() = println("汪汪!")
}

class DogAbstract : AnimalAbstract("狗狗") {
    override val name: String = "狗狗"
    override fun makeSound() = println("汪汪!")
}

7. 接口委托

使用 by 关键字委托实现

kotlin 复制代码
interface Repository {
    fun save(data: String)
    fun load(id: String): String?
}

class DatabaseRepository : Repository {
    override fun save(data: String) {
        println("保存到数据库: $data")
    }
    
    override fun load(id: String): String? {
        println("从数据库加载: $id")
        return "数据"
    }
}

// 委托给 DatabaseRepository
class CachedRepository(private val repository: Repository) : Repository by repository {
    private val cache = mutableMapOf<String, String>()
    
    // 只重写需要定制的方法
    override fun load(id: String): String? {
        return cache[id] ?: repository.load(id)?.also {
            cache[id] = it
        }
    }
    
    // 新增方法
    fun clearCache() {
        cache.clear()
    }
}

属性委托到接口

kotlin 复制代码
interface Logger {
    fun log(message: String)
}

class ConsoleLogger : Logger {
    override fun log(message: String) {
        println("控制台日志: $message")
    }
}

class Service(logger: Logger) {
    private val logger: Logger by lazy { logger }
    
    fun doWork() {
        logger.log("开始工作")
        // 工作逻辑
        logger.log("工作完成")
    }
}

8. 接口中的内联方法

kotlin 复制代码
interface JsonSerializable {
    fun toJson(): String
    
    // 内联方法
    inline fun printJson() {
        println(toJson())
    }
}

data class Person(val name: String, val age: Int) : JsonSerializable {
    override fun toJson(): String {
        return """{"name": "$name", "age": $age}"""
    }
}

// 使用
val person = Person("Alice", 30)
person.printJson()  // 内联展开

9. 接口中的扩展函数

kotlin 复制代码
interface Sortable<T> {
    fun compare(other: T): Int
}

// 为接口定义扩展函数
fun <T : Sortable<T>> List<T>.sorted(): List<T> {
    return this.sortedWith { a, b -> a.compare(b) }
}

// 为接口定义扩展属性
val Sortable<*>.hash: Int
    get() = hashCode()

// 使用示例
data class Product(val name: String, val price: Double) : Sortable<Product> {
    override fun compare(other: Product): Int {
        return price.compareTo(other.price)
    }
}

val products = listOf(
    Product("A", 100.0),
    Product("B", 50.0),
    Product("C", 75.0)
)

val sorted = products.sorted()  // 使用扩展函数

10. 接口的实用模式

标记接口

kotlin 复制代码
// 标记接口(没有任何方法)
interface Serializable

// 使用
data class Document(val content: String) : Serializable

fun saveIfSerializable(obj: Any) {
    if (obj is Serializable) {
        println("保存对象: $obj")
    }
}

构建器模式接口

kotlin 复制代码
interface Builder<T> {
    fun build(): T
}

class CarBuilder : Builder<Car> {
    private var color = "红色"
    private var wheels = 4
    
    fun setColor(color: String) = apply { this.color = color }
    fun setWheels(wheels: Int) = apply { this.wheels = wheels }
    
    override fun build(): Car {
        return Car(color, wheels)
    }
}

data class Car(val color: String, val wheels: Int)

// 使用
val car = CarBuilder()
    .setColor("蓝色")
    .setWheels(4)
    .build()

策略模式接口

kotlin 复制代码
interface PaymentStrategy {
    fun pay(amount: Double): Boolean
}

class CreditCardPayment : PaymentStrategy {
    override fun pay(amount: Double): Boolean {
        println("信用卡支付: $$amount")
        return true
    }
}

class PayPalPayment : PaymentStrategy {
    override fun pay(amount: Double): Boolean {
        println("PayPal支付: $$amount")
        return true
    }
}

class ShoppingCart(private var paymentStrategy: PaymentStrategy) {
    fun checkout(amount: Double) {
        paymentStrategy.pay(amount)
    }
    
    fun changeStrategy(strategy: PaymentStrategy) {
        paymentStrategy = strategy
    }
}

11. 接口的协变和逆变

kotlin 复制代码
// 协变接口(out 关键字)
interface Producer<out T> {
    fun produce(): T
}

// 逆变接口(in 关键字)
interface Consumer<in T> {
    fun consume(item: T)
}

// 使用示例
class FruitProducer : Producer<Fruit> {
    override fun produce(): Fruit = Fruit()
}

class AppleProducer : Producer<Apple> {
    override fun produce(): Apple = Apple()
}

open class Fruit
class Apple : Fruit()

fun useProducer(producer: Producer<Fruit>) {
    val fruit: Fruit = producer.produce()
}

// 协变允许 Producer<Apple> 赋值给 Producer<Fruit>
val fruitProducer: Producer<Fruit> = AppleProducer()

12. 接口的最佳实践

kotlin 复制代码
// 1. 单一职责原则
interface Savable {
    fun save()
}

interface Loadable {
    fun load()
}

// 2. 接口隔离原则(不要强迫客户端依赖它们不用的方法)
interface Printer {
    fun print()
}

interface Scanner {
    fun scan()
}

// 3. 使用默认实现减少样板代码
interface Repository<T> {
    fun save(item: T)
    fun findById(id: String): T?
    fun findAll(): List<T>
    
    // 默认实现
    fun existsById(id: String): Boolean {
        return findById(id) != null
    }
}

// 4. 使用函数式接口简化回调
fun interface OnSuccess<T> {
    fun onSuccess(result: T)
}

fun <T> doAsync(
    operation: () -> T,
    onSuccess: OnSuccess<T>
) {
    val result = operation()
    onSuccess.onSuccess(result)
}

// 使用
doAsync(
    operation = { "结果" },
    onSuccess = { println("成功: $it") }
)

总结

Kotlin 接口提供了比 Java 接口更强大的功能:

  • 默认方法实现:减少实现类的样板代码
  • 属性支持:可以定义抽象属性和带 getter/setter 的属性
  • 多继承:一个类可以实现多个接口
  • 函数式接口:支持 SAM 转换,简化回调
  • 私有方法:Kotlin 1.7+ 支持接口中的私有方法
  • 委托模式 :使用 by 关键字委托接口实现

接口在 Kotlin 中是实现抽象、多态和解耦代码的重要工具。

相关推荐
StarShip2 小时前
Android Context 的 “上下文”
android
李小轰_Rex2 小时前
纯算法AEC:播录并行场景的回声消除实战笔记
android·音视频开发
ok406lhq3 小时前
unity游戏调用SDK支付返回游戏会出现画面移位的问题
android·游戏·unity·游戏引擎·sdk
成都大菠萝4 小时前
2-2-2 快速掌握Kotlin-函数&Lambda
android
成都大菠萝4 小时前
2-1-1 快速掌握Kotlin-kotlin中变量&语句&表达式
android
CC.GG4 小时前
【C++】STL----封装红黑树实现map和set
android·java·c++
renke33645 小时前
Flutter 2025 跨平台工程体系:从 iOS/Android 到 Web/Desktop,构建真正“一次编写,全端运行”的产品
android·flutter·ios
儿歌八万首5 小时前
Android 自定义 View :打造一个跟随滑动的丝滑指示器
android
yueqc15 小时前
Android System Lib 梳理
android·lib