Kotlin 函数接口与普通接口的区别
记一次编写Demo时SonarLint提示警告而关注到的kotlin1.4新增的接口声明方式.
// SonarLint警告: Make this interface functional or replace it with a function type.
interface GitHubService {
@GET("search/repositories?sort=stars&q=Android")
suspend fun searchRepos(@Query("page") page: Int, @Query("per_page") perPage: Int): GitHubResponse
}
// 声明为函数接口后修复警告
fun interface GitHubService {
@GET("search/repositories?sort=stars&q=Android")
suspend fun searchRepos(@Query("page") page: Int, @Query("per_page") perPage: Int): GitHubResponse
}
普通接口
当使用 interface
关键字定义接口时,可以声明抽象方法和默认方法。抽象方法是没有具体实现的方法,需要在实现接口的类中提供具体的实现。默认方法是在接口中提供了一个默认的实现,实现类可以选择重写或者直接使用默认实现。
interface GitHubService {
fun getUser(username: String): User // 抽象方法
fun getRepositories(username: String): List<Repository> { // 默认方法
val user = getUser(username)
// 通过用户获取仓库列表的具体实现
// ...
return repositories
}
}
函数接口
使用 fun interface
声明的接口只能包含一个抽象方法,并且不能包含默认方法。这种类型的接口通常用于函数式编程和 lambda 表达式的场景。实现这个接口的类可以通过 lambda 表达式或者函数引用来提供方法的具体实现。
fun interface GitHubService {
fun getUser(username: String): User
}
// 通过 lambda 表达式为 getUser 方法提供了具体的实现。
// lambda 表达式接收一个用户名参数,并返回对应的用户对象。
val service = GitHubService { username ->
// 通过用户名获取用户的具体实现
// ...
return user
}
常见使用场景
interface
-
定义回调接口:接口可以用作定义回调函数的契约。一个类可以实现接口并提供回调方法的具体实现,然后将实现类的实例传递给其他需要回调的组件。
-
实现多态行为:接口可以作为多态的手段,使得不同的类可以以不同的方式实现相同的接口。这种多态的特性允许在运行时根据对象的具体类型调用相应的方法。
-
定义服务接口:接口可以定义服务契约,描述系统的服务功能,并规定服务方法的签名。其他模块或组件可以实现接口,并提供具体的服务实现。
-
定义插件机制:接口可以用于定义插件的扩展点。主应用程序定义接口,并提供默认实现,而插件可以实现这个接口并提供自定义的行为。
-
实现策略模式:接口可以用于实现策略模式,其中不同的类实现相同的接口,并提供不同的算法或策略。
fun interface
-
定义函数式接口:函数式接口只包含一个抽象方法,通常用于表示某个操作或行为。这样的接口可以作为函数类型的参数或返回值,使得函数可以被传递、组合和使用。
-
使用 lambda 表达式:函数式接口可以通过 lambda 表达式提供方法的具体实现。这种方式使得代码更加简洁、易读,并支持函数式编程的风格。
-
支持函数引用:函数式接口可以与函数引用一起使用,允许直接引用已有的函数作为接口的实现。这样可以减少冗余的代码,并提高代码的可读性。
总而言之,interface
关键字适用于一般的接口定义和多态行为,而 fun interface
关键字则适用于函数式编程和 lambda 表达式的场景。
总结一下,interface
关键字用于定义常规的接口,可以包含抽象方法和默认方法。而 fun interface
关键字用于定义函数式接口,只能包含一个抽象方法,并且不能包含默认方法。