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 中是实现抽象、多态和解耦代码的重要工具。