Kotlin接口全面解析:从基础到高级应用
2026/9/13 5:03:24 网站建设 项目流程

1. Kotlin接口基础概念解析

Kotlin接口是一种定义行为契约的强大工具,它允许我们声明一组抽象方法和属性,而无需关心具体实现。与Java接口相比,Kotlin接口具有更丰富的特性,这也是为什么它成为现代Kotlin开发中不可或缺的部分。

1.1 接口的本质与作用

接口在Kotlin中通过interface关键字定义,它本质上是一组抽象成员的集合。与抽象类不同,接口不能保存状态(尽管可以通过属性访问器实现类似功能),这使得它成为定义纯行为的理想选择。

接口的核心价值体现在三个方面:

  1. 多继承支持:Kotlin类可以实现多个接口,解决了单继承语言的局限性
  2. 契约式编程:明确规定了实现类必须提供哪些功能
  3. 解耦:将定义与实现分离,提高代码的灵活性和可维护性
interface Clickable { fun click() fun showOff() = println("I'm clickable!") // 带默认实现的方法 }

1.2 接口与抽象类的区别

虽然接口和抽象类都包含抽象成员,但它们有本质区别:

特性接口抽象类
继承机制可实现多个只能继承一个
状态保存不能保存状态可以保存状态
构造函数不能有主/次构造函数可以有构造函数
成员初始化属性不能初始化属性可以初始化
使用场景定义行为契约提供部分实现

实际开发中的经验法则:当你主要需要定义一组相关操作时使用接口,当需要共享代码或维护状态时考虑抽象类。

2. Kotlin接口的高级特性

2.1 默认方法实现

Kotlin接口允许为方法提供默认实现,这是与Java 8之前接口的重大区别。这个特性使得接口演化变得更加容易——你可以向接口添加新方法并提供默认实现,而不必强制所有实现类都立即实现新方法。

interface UserRepository { fun add(user: User) fun get(id: Int): User? // 默认实现 fun contains(id: Int): Boolean { return get(id) != null } }

注意事项

  • 默认方法会带来"菱形继承"问题,当多个接口有相同方法签名时,实现类必须明确指定使用哪个默认实现
  • 默认方法不应包含复杂逻辑,保持简单职责
  • 避免在默认方法中访问状态,这可能导致意外行为

2.2 属性声明

Kotlin接口可以声明属性,但这些属性要么是抽象的,要么必须提供访问器实现。接口中的属性不能有幕后字段(field),因此不能直接初始化。

interface Person { val name: String // 抽象属性 val age: Int // 提供getter实现 get() = 0 }

实现类可以通过多种方式满足接口属性要求:

class Employee(override val name: String) : Person { // age使用接口默认实现 } class Student : Person { override val name: String get() = "Student" override val age: Int = 20 // 也可以覆盖 }

2.3 函数式接口(SAM接口)

对于只有一个抽象方法的接口(Single Abstract Method,简称SAM),Kotlin提供了特殊的语法糖,允许使用lambda表达式实现:

fun interface Transformer { fun transform(input: String): String } val upperCaseTransformer = Transformer { it.uppercase() }

使用场景

  • 事件监听器
  • 回调函数
  • 策略模式实现

从Kotlin 1.4开始,必须显式使用fun interface声明才能启用SAM转换功能。

3. 接口的继承与组合

3.1 接口继承

Kotlin接口可以继承其他接口,形成接口层次结构。这允许我们构建更精细的契约:

interface Clickable { fun click() } interface Scrollable : Clickable { fun scroll() fun showOff() = println("I'm scrollable!") } class Page : Scrollable { override fun click() = println("Page clicked") override fun scroll() = println("Page scrolled") // 可以选择是否覆盖showOff }

3.2 多接口继承冲突解决

当实现多个接口且这些接口有相同方法签名时,必须明确指定使用哪个实现:

interface A { fun foo() { println("A") } } interface B { fun foo() { println("B") } } class C : A, B { override fun foo() { super<A>.foo() // 明确调用A的实现 super<B>.foo() // 明确调用B的实现 } }

最佳实践

  • 避免设计有方法签名冲突的接口
  • 如果冲突不可避免,在实现类中提供明确解决方案
  • 考虑使用组合代替多重继承

3.3 接口委托

Kotlin通过by关键字支持委托模式,这是处理接口实现的强大工具:

interface DataStorage { fun save(data: String) fun load(): String } class FileStorage : DataStorage { override fun save(data: String) { /* 实现 */ } override fun load(): String { /* 实现 */ } } class SecureStorage(private val storage: DataStorage) : DataStorage by storage { // 可以只覆盖部分方法 override fun save(data: String) { storage.save(encrypt(data)) } private fun encrypt(data: String): String { /* 加密逻辑 */ } }

委托模式的优势

  • 实现真正的零样板代码委托
  • 轻松实现装饰器模式
  • 方便进行功能扩展和修改

4. Kotlin接口在实际项目中的应用

4.1 策略模式实现

接口是策略模式的天然实现方式:

interface DiscountStrategy { fun applyDiscount(amount: Double): Double } class NoDiscount : DiscountStrategy { override fun applyDiscount(amount: Double) = amount } class PercentageDiscount(private val percentage: Double) : DiscountStrategy { override fun applyDiscount(amount: Double) = amount * (1 - percentage/100) } class Order(private val discountStrategy: DiscountStrategy) { fun checkout(amount: Double): Double { return discountStrategy.applyDiscount(amount) } }

4.2 回调机制

接口常用于实现回调机制:

interface DownloadCallback { fun onStart() fun onProgress(percent: Int) fun onComplete(data: ByteArray) fun onError(exception: Exception) } class FileDownloader(private val callback: DownloadCallback) { fun download(url: String) { callback.onStart() try { // 模拟下载 for (i in 1..100) { Thread.sleep(50) callback.onProgress(i) } callback.onComplete(ByteArray(0)) } catch (e: Exception) { callback.onError(e) } } }

4.3 模块间通信

接口是模块间解耦的理想选择:

// 在core模块定义接口 interface AuthService { fun login(username: String, password: String): Boolean fun logout() } // 在app模块实现 class FirebaseAuthService : AuthService { override fun login(username: String, password: String): Boolean { // Firebase实现 } override fun logout() { // Firebase实现 } } // 在其他模块通过接口使用 class UserProfile(val authService: AuthService) { fun showProfile() { if (!authService.login("user", "pass")) { println("Login failed") } } }

5. 接口设计的最佳实践与陷阱

5.1 接口设计原则

  1. 单一职责原则:每个接口应该只关注一个特定功能领域
  2. 小而美:保持接口精简,避免"胖接口"
  3. 命名清晰:使用-able后缀命名行为接口(如RunnableComparable
  4. 文档完整:为所有公共接口成员提供KDoc文档
  5. 稳定性:一旦发布,尽量避免修改接口

5.2 常见陷阱与解决方案

陷阱1:过度使用默认方法

  • 问题:默认方法过多会导致接口变得臃肿
  • 解决方案:将相关默认方法提取到单独的接口或扩展函数中

陷阱2:接口泄漏

  • 问题:内部实现细节通过接口暴露
  • 解决方案:为不同客户端提供不同的接口视图

陷阱3:状态管理

  • 问题:试图通过接口属性维护状态
  • 解决方案:使用抽象类或组合模式来管理状态

5.3 接口与扩展函数的结合

Kotlin扩展函数可以与接口协同工作,提供更灵活的设计:

interface JsonSerializable { fun toJson(): String } // 为所有JsonSerializable提供扩展函数 fun JsonSerializable.prettyPrint(): String { return JsonParser.parseString(toJson()).toString() } class User : JsonSerializable { override fun toJson() = """{"name":"John"}""" } // 使用 val user = User() println(user.prettyPrint())

这种组合方式允许我们:

  • 保持接口精简
  • 通过扩展添加辅助功能
  • 实现功能的按需导入

6. Kotlin接口在Android开发中的实际案例

6.1 RecyclerView适配器中的接口

interface OnItemClickListener<T> { fun onItemClick(item: T, position: Int) } class MyAdapter<T>( private val items: List<T>, private val listener: OnItemClickListener<T> ) : RecyclerView.Adapter<MyViewHolder<T>>() { override fun onBindViewHolder(holder: MyViewHolder<T>, position: Int) { holder.bind(items[position]) holder.itemView.setOnClickListener { listener.onItemClick(items[position], position) } } } // 使用 adapter = MyAdapter(dataList, object : OnItemClickListener<Data> { override fun onItemClick(item: Data, position: Int) { // 处理点击 } })

6.2 ViewModel与UI通信

interface LoginViewModel { val state: LiveData<LoginState> fun login(username: String, password: String) } class LoginActivity : AppCompatActivity() { private val viewModel: LoginViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) viewModel.state.observe(this) { state -> when (state) { is Loading -> showProgress() is Success -> navigateToHome() is Error -> showError(state.message) } } loginButton.setOnClickListener { viewModel.login( usernameEditText.text.toString(), passwordEditText.text.toString() ) } } }

6.3 跨模块依赖解耦

在大型Android项目中,接口是解耦模块依赖的关键:

// 在:features:profile模块定义 interface UserProfileDependencies { fun userRepository(): UserRepository fun imageLoader(): ImageLoader } // 在:app模块实现 class AppDependencies : UserProfileDependencies { override fun userRepository() = UserRepositoryImpl() override fun imageLoader() = GlideImageLoader() } // 在:features:profile模块使用 class ProfileViewModel(dependencies: UserProfileDependencies) { private val userRepo = dependencies.userRepository() private val imageLoader = dependencies.imageLoader() // ... }

这种模式通过接口完全解耦了功能模块与应用基础设施的依赖关系。

7. Kotlin接口与协程的结合

7.1 异步操作接口

interface NewsRepository { suspend fun fetchLatestNews(): List<News> suspend fun fetchNewsDetail(id: String): NewsDetail } class NewsRepositoryImpl( private val api: NewsApi, private val db: NewsDatabase ) : NewsRepository { override suspend fun fetchLatestNews(): List<News> { return try { val news = api.getLatestNews() db.saveNews(news) news } catch (e: Exception) { db.getCachedNews() } } // ...其他实现 }

7.2 Flow在接口中的应用

interface StockPriceMonitor { fun monitorStock(symbol: String): Flow<PriceUpdate> suspend fun getCurrentPrice(symbol: String): PriceUpdate } class RealStockPriceMonitor( private val stockService: StockService ) : StockPriceMonitor { override fun monitorStock(symbol: String): Flow<PriceUpdate> { return stockService.getPriceUpdates(symbol) .catch { e -> emit(PriceUpdate.Error(e)) } } override suspend fun getCurrentPrice(symbol: String): PriceUpdate { return try { stockService.getCurrentPrice(symbol) } catch (e: Exception) { PriceUpdate.Error(e) } } }

7.3 协程作用域管理

interface CoroutineScopeOwner { val coroutineScope: CoroutineScope } class ActivityScopeOwner(activity: ComponentActivity) : CoroutineScopeOwner { override val coroutineScope: CoroutineScope = activity.lifecycleScope } class Presenter( scopeOwner: CoroutineScopeOwner, private val repository: NewsRepository ) { private val scope = scopeOwner.coroutineScope fun loadNews() { scope.launch { val news = repository.fetchLatestNews() // 更新UI } } }

8. Kotlin接口的高级技巧与性能考量

8.1 内联类实现接口

Kotlin内联类可以实现接口,这在需要类型安全又不想引入运行时开销时非常有用:

interface Id { val value: String } @JvmInline value class UserId(override val value: String) : Id @JvmInline value class ProductId(override val value: String) : Id fun processUserId(id: UserId) { println("Processing user ${id.value}") } // 使用 val userId = UserId("123") val productId = ProductId("456") processUserId(userId) // 正确 // processUserId(productId) // 编译错误,类型不匹配

8.2 接口与类型别名结合

类型别名可以简化复杂接口类型的声明:

typealias ItemClickListener<T> = (T, Int) -> Unit interface Adapter<T> { var itemClick: ItemClickListener<T> } class MyAdapter<T> : Adapter<T> { override var itemClick: ItemClickListener<T> = { _, _ -> } }

8.3 接口性能考量

  1. 方法调用开销:接口方法调用比类方法调用稍慢(约10%),但在大多数情况下可以忽略
  2. 内存占用:每个接口实例会带来少量内存开销
  3. Proguard优化:合理配置Proguard可以减少接口带来的运行时开销

性能优化建议

  • 在性能关键路径避免深度接口继承
  • 考虑使用final类实现高频调用的接口
  • 对于简单接口,可以使用函数类型替代

8.4 接口与Kotlin/JS和Kotlin/Native

在多平台项目中,接口的行为可能有所不同:

  1. Kotlin/JS

    • 接口编译为JavaScript的抽象方法
    • 默认方法会被复制到实现类中
    • 接口性能与ES6类相当
  2. Kotlin/Native

    • 接口调用有与JVM类似的轻微开销
    • 在iOS交互中,接口是定义Kotlin与Swift/Obj-C协议的最佳方式
// 多平台接口定义 expect interface PlatformFileSystem { fun readFile(path: String): String fun writeFile(path: String, content: String) } // JVM实现 actual class JvmFileSystem : PlatformFileSystem { actual override fun readFile(path: String): String { return File(path).readText() } actual override fun writeFile(path: String, content: String) { File(path).writeText(content) } }

9. Kotlin接口的未来发展趋势

随着Kotlin语言的演进,接口功能仍在不断增强:

  1. 上下文接收器(Context Receivers): 未来版本可能会引入更优雅的接口组合方式
// 实验性功能 interface LoggingContext { val logger: Logger } context(LoggingContext) interface Service { fun execute() { logger.info("Executing...") } }
  1. 多平台接口改进

    • 更好的平台特定接口实现检测
    • 更高效的多平台接口代码生成
  2. 接口与元编程: 结合Kotlin的元编程能力,接口可能会支持更强大的运行时行为修改

10. 从Java接口到Kotlin接口的迁移策略

对于Java开发者转向Kotlin,接口使用有一些需要注意的差异点:

  1. 默认方法处理

    • Kotlin中所有非抽象接口方法都是默认方法
    • 与Java 8+的默认方法二进制兼容
  2. 静态方法: Kotlin接口不能包含静态方法,应使用伴生对象或顶层函数替代

  3. 函数式接口: Kotlin中需要显式声明fun interface才能获得SAM转换支持

迁移步骤建议

  1. 将Java接口转换为Kotlin接口
  2. 检查所有默认方法实现
  3. 将静态方法转换为伴生对象成员
  4. 考虑将适合的接口标记为fun interface
  5. 利用Kotlin的属性语法简化getter/setter

示例迁移

// Java接口 public interface DataProcessor { void process(Data data); default void validate(Data data) { // 验证逻辑 } static DataProcessor create() { return new DefaultDataProcessor(); } }
// 迁移后的Kotlin接口 interface DataProcessor { fun process(data: Data) fun validate(data: Data) { // 验证逻辑 } companion object { fun create(): DataProcessor = DefaultDataProcessor() } }

11. Kotlin接口在函数式编程中的应用

Kotlin支持函数式编程风格,接口在其中扮演重要角色:

11.1 代数数据类型(ADT)

sealed interface Result<out T> { data class Success<out T>(val value: T) : Result<T> data class Error(val exception: Throwable) : Result<Nothing> } fun handleResult(result: Result<String>) { when(result) { is Result.Success -> println(result.value) is Result.Error -> println("Error: ${result.exception}") } }

11.2 高阶函数与接口

interface Transformer<T, R> { fun transform(input: T): R } fun <T, R> List<T>.map(transformer: Transformer<T, R>): List<R> { return this.map { transformer.transform(it) } } // 使用 val stringToLength = object : Transformer<String, Int> { override fun transform(input: String) = input.length } val lengths = listOf("a", "ab", "abc").map(stringToLength)

11.3 函数式模式实现

Monad模式示例

interface Monad<out T> { fun <R> flatMap(f: (T) -> Monad<R>): Monad<R> } class Maybe<out T>(val value: T?) : Monad<T> { override fun <R> flatMap(f: (T) -> Monad<R>): Monad<R> { return value?.let { f(it) } ?: Maybe(null) } }

12. 接口与Kotlin DSL设计

接口是构建类型安全DSL的重要工具:

interface SqlQueryBuilder { fun select(vararg columns: String): SqlQueryBuilder fun from(table: String): SqlQueryBuilder fun where(condition: String): SqlQueryBuilder fun build(): String } class SimpleSqlQueryBuilder : SqlQueryBuilder { private val parts = mutableListOf<String>() override fun select(vararg columns: String): SqlQueryBuilder { parts.add("SELECT ${columns.joinToString(", ")}") return this } override fun from(table: String): SqlQueryBuilder { parts.add("FROM $table") return this } override fun where(condition: String): SqlQueryBuilder { parts.add("WHERE $condition") return this } override fun build(): String { return parts.joinToString(" ") } } // 使用 val query = SimpleSqlQueryBuilder() .select("id", "name", "email") .from("users") .where("age > 21") .build()

DSL设计技巧

  1. 使用接口定义DSL语法
  2. 通过返回this实现流畅接口
  3. 为常用操作提供扩展函数
  4. 使用带接收者的lambda进一步简化语法

13. 接口与依赖注入框架

现代依赖注入框架如Koin、Dagger等都重度依赖接口:

13.1 Koin示例

interface DatabaseService { fun executeQuery(sql: String): ResultSet } class ProductionDatabaseService : DatabaseService { override fun executeQuery(sql: String): ResultSet { // 实际数据库操作 } } // 模块定义 val appModule = module { single<DatabaseService> { ProductionDatabaseService() } } // 使用 class UserRepository(private val db: DatabaseService) { fun getUsers(): List<User> { val result = db.executeQuery("SELECT * FROM users") // 处理结果 } }

13.2 接口与测试替身

接口使得创建测试替身(Test Double)变得简单:

class TestDatabaseService : DatabaseService { private val data = mutableMapOf<String, List<Map<String, Any>>>() fun addTestData(table: String, rows: List<Map<String, Any>>) { data[table] = rows } override fun executeQuery(sql: String): ResultSet { // 解析SQL并返回测试数据 return MockResultSet(data) } } class UserRepositoryTest { @Test fun testGetUsers() { val testDb = TestDatabaseService().apply { addTestData("users", listOf( mapOf("id" to 1, "name" to "Alice"), mapOf("id" to 2, "name" to "Bob") )) } val repo = UserRepository(testDb) val users = repo.getUsers() assertEquals(2, users.size) } }

14. Kotlin接口的调试与性能分析

14.1 调试接口调用

  1. 断点技巧

    • 在接口方法上设置断点会捕获所有实现类的调用
    • 使用条件断点过滤特定实现类
  2. 调用栈分析

    • 注意接口方法调用的间接性
    • 使用"Show Implementations"功能快速导航到具体实现

14.2 性能分析

  1. CPU分析

    • 接口方法调用在调用图上显示为"invokeinterface"
    • 对比直接方法调用("invokevirtual")的开销
  2. 内存分析

    • 接口引用比类引用多消耗约4字节内存
    • 注意接口作为集合元素类型时的内存影响

优化建议

  • 对高频调用的热路径考虑使用final类
  • 在性能关键代码中减少接口层次深度
  • 必要时使用内联类包装接口实现

15. 接口与Kotlin元编程

Kotlin的反射API可以用于接口的运行时分析:

interface MyInterface { fun doSomething() val someProperty: String } fun analyzeInterface() { val kClass = MyInterface::class println("Interface ${kClass.qualifiedName}") println("Functions:") kClass.memberFunctions.forEach { fn -> println("- ${fn.name} with ${fn.parameters.size} parameters") } println("Properties:") kClass.memberProperties.forEach { prop -> println("- ${prop.name} of type ${prop.returnType}") } }

元编程应用场景

  • 自动生成接口实现
  • 运行时接口验证
  • 动态代理创建
  • 序列化/反序列化框架

16. Kotlin接口的跨平台应用

16.1 多平台项目中的接口

在Kotlin多平台项目中,接口是共享代码的核心工具:

// 公共模块 expect interface PlatformStorage { fun saveData(key: String, value: String) fun loadData(key: String): String? } // 平台特定实现 // JVM actual class JvmStorage : PlatformStorage { actual override fun saveData(key: String, value: String) { Files.writeString(Path.of(key), value) } actual override fun loadData(key: String): String? { return if (Files.exists(Path.of(key))) { Files.readString(Path.of(key)) } else null } } // JS actual class JsStorage : PlatformStorage { actual override fun saveData(key: String, value: String) { localStorage.setItem(key, value) } actual override fun loadData(key: String): String? { return localStorage.getItem(key) } }

16.2 接口与Swift/Obj-C互操作

在Kotlin/Native中,接口可以暴露给Swift/Obj-C代码:

@ObjCName("DatabaseService") interface DatabaseService { @ObjCName("executeQuery") fun executeQuery(sql: String): ResultSet } class iOSDatabaseService : DatabaseService { override fun executeQuery(sql: String): ResultSet { // 实现 } }

在Swift中可以直接使用:

let service: DatabaseService = iOSDatabaseService() let result = service.executeQuery(withSql: "SELECT * FROM users")

17. Kotlin接口的版本兼容性策略

随着项目演进,接口可能需要变更,以下是保持兼容性的策略:

  1. 添加而非修改

    • 添加新方法时提供默认实现
    • 避免修改现有方法签名
  2. 弃用而非删除

    interface MyInterface { @Deprecated("Use newMethod instead", ReplaceWith("newMethod()")) fun oldMethod() fun newMethod() { oldMethod() // 默认实现保持兼容 } }
  3. 接口拆分: 当接口变得臃肿时,将其拆分为多个更专注的接口

  4. 版本化接口

    interface MyInterfaceV1 { fun methodV1() } interface MyInterfaceV2 : MyInterfaceV1 { fun methodV2() @Deprecated("Implemented in V1 interface") override fun methodV1() { // 默认实现 } }

18. Kotlin接口的测试策略

18.1 接口契约测试

确保所有实现类都遵守接口契约:

abstract class MyInterfaceContractTest { abstract fun createImplementation(): MyInterface @Test fun `should return non-null value`() { val impl = createImplementation() assertNotNull(impl.doSomething()) } @Test fun `should handle null input`() { val impl = createImplementation() assertDoesNotThrow { impl.handleInput(null) } } } class MyInterfaceImplTest : MyInterfaceContractTest() { override fun createImplementation() = MyInterfaceImpl() }

18.2 默认方法测试

即使有默认实现,也应测试默认行为:

class MyInterfaceDefaultsTest { private val testImpl = object : MyInterface { // 仅实现抽象成员 override fun abstractMethod() = "test" } @Test fun `default method should return combined result`() { assertEquals("test-default", testImpl.combinedMethod()) } }

18.3 模拟接口

使用MockK等框架模拟接口:

@Test fun `should call dependency`() { val mockDep = mockk<MyInterface>() every { mockDep.doSomething() } returns "mocked" val sut = SystemUnderTest(mockDep) sut.execute() verify { mockDep.doSomething() } }

19. Kotlin接口的文档化

良好的文档对接口尤为重要,Kotlin的KDoc支持丰富的文档标记:

/** * 表示一个可以渲染的组件 * * 实现类必须确保: * - 线程安全 * - 支持多次渲染 * - 正确处理null属性 * * @see TextView 默认实现 * @sample com.example.RenderableSamples.basicUsage */ interface Renderable { /** * 将组件渲染到指定上下文 * @param context 渲染上下文,不能为null * @return 渲染是否成功 * @throws RenderException 当渲染失败时抛出 */ fun render(context: RenderContext): Boolean /** * 组件是否可见 * * 默认实现返回true,表示组件默认可见 */ val isVisible: Boolean get() = true }

文档最佳实践

  1. 描述接口的总体职责和契约
  2. 为每个成员提供详细文档
  3. 使用@see引用相关类型
  4. 使用@sample提供示例代码
  5. 记录线程安全要求

20. 从设计模式看Kotlin接口

20.1 工厂模式

interface Animal { fun speak(): String } class Dog : Animal { override fun speak() = "Woof!" } class Cat : Animal { override fun speak() = "Meow!" } interface AnimalFactory { fun createAnimal(type: String): Animal } class SimpleAnimalFactory : AnimalFactory { override fun createAnimal(type: String): Animal { return when (type.lowercase()) { "dog" -> Dog() "cat" -> Cat() else -> throw IllegalArgumentException("Unknown animal type") } } }

20.2 观察者模式

interface EventListener { fun onEvent(event: Event) } class EventManager { private val listeners = mutableListOf<EventListener>() fun addListener(listener: EventListener) { listeners.add(listener) } fun notify(event: Event) { listeners.forEach { it.onEvent(event) } } } class Logger : EventListener { override fun onEvent(event: Event) { println("Event received: $event") } }

20.3 策略模式

interface CompressionStrategy { fun compress(input: ByteArray): ByteArray } class ZipCompression : CompressionStrategy { override fun compress(input: ByteArray): ByteArray { // Zip实现 } } class GzipCompression : CompressionStrategy { override fun compress(input: ByteArray): ByteArray { // Gzip实现 } } class Compressor(private val strategy: CompressionStrategy) { fun compressData(data: ByteArray): ByteArray { return strategy.compress(data) } }

21. Kotlin接口与Java互操作

21.1 从Java实现Kotlin接口

Kotlin接口可以无缝被Java实现:

// Kotlin接口 interface StringProcessor { fun process(input: String): String fun validate(input: String): Boolean { return input.isNotEmpty() } }
// Java实现 public class JavaStringProcessor implements StringProcessor { @Override public String process(String input) { return input.toUpperCase(); } // 可以选择是否覆盖默认方法 }

21.2 从Kotlin实现Java接口

Kotlin可以更简洁地实现Java接口:

// Java接口 public interface JavaCalculator { int add(int a, int b); default int square(int x) { return x * x; } }
// Kotlin实现 object KotlinCalculator : JavaCalculator { override fun add(a: Int, b: Int) = a + b // 可以选择是否覆盖默认方法 }

21.3 二进制兼容性注意事项

  1. 默认方法

    • Kotlin 1.4+与Java 8+的默认方法二进制兼容
    • 旧版本可能需要@JvmDefault注解
  2. 属性: Kotlin接口属性会编译为Java的getter/setter方法对

  3. 泛型差异: 注意Kotlin的声明处型变与Java通配符的映射关系

22. Kotlin接口与泛型

22.1 泛型接口基础

interface Repository<T> { fun getById(id: String): T? fun getAll(): List<T> fun save(entity: T) } class UserRepository : Repository<User> { private val store = mutableMapOf<String, User>() override fun getById(id: String): User? = store[id] override fun getAll(): List<User> = store.values.toList() override fun save(entity: User) { store[entity.id] = entity } }

22.2 型变注解

Kotlin支持在接口上声明型变:

interface Producer<out T> { fun produce(): T } interface Consumer<in T> { fun consume(item: T) } // 使用 val stringProducer: Producer<String> = object : Producer<String> { override fun produce() = "Hello" } val anyProducer: Producer<Any> = stringProducer // 协变安全 val anyConsumer: Consumer<Any> = object : Consumer<Any> { override fun consume(item: Any) { println(item) } } val stringConsumer: Consumer<String> = anyConsumer // 逆变安全

22.3 泛型约束

interface ComparableList<T : Comparable<T>> : List<T> { fun max(): T? fun min(): T? fun sort(): List<T> } class IntList : ComparableList<Int> { // 必须实现List<Int>和ComparableList<Int>的所有成员 }

23. Kotlin接口与注解处理

接口常与注解处理器配合使用:

@Target(AnnotationTarget.CLASS) @Retention(AnnotationRetention.SOURCE) annotation class Factory(val type: KClass<*>) interface Animal { val name: String } @Factory(Dog::class) class Dog : Animal { override val name = "Dog" } @Factory(Cat::class) class Cat : Animal { override val name = "Cat" } // 注解处理器可以生成如下代码 object AnimalFactory { fun create(type: KClass<*>): Animal { return when (type) { Dog::class -> Dog() Cat::class -> Cat() else -> throw IllegalArgumentException("Unknown animal type") } } }

24. Kotlin接口与编译器插件

高级开发者可以创建编译器插件来增强接口功能:

  1. 接口方法生成: 自动为接口生成

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询