詳解如何實(shí)現(xiàn)一個(gè)Kotlin函數(shù)類型
接口與函數(shù)類型
業(yè)務(wù)開發(fā)中,經(jīng)常會(huì)有實(shí)現(xiàn)一個(gè)函數(shù)式接口(即接口只有一個(gè)方法需要實(shí)現(xiàn))的場景,大家應(yīng)該都會(huì)不假思索的寫出如下代碼:
interface Callback {
fun response(): String
}
class Achieve: Callback {
override fun response(): String {
return ""
}
}這么寫當(dāng)然沒什么毛病,甚至為了讓kotlin支持對(duì)接口Callback的SAM轉(zhuǎn)換,你還可以在接口前面增加一個(gè)fun修飾:
fun interface Callback {
fun response()
}但是對(duì)于Kotlin而言,本身函數(shù)類型是可以被實(shí)現(xiàn)的,也就是說我們可以使用函數(shù)類型替換函數(shù)式接口,讓子類去實(shí)現(xiàn),代碼如下:
class Achieve: () -> String {
override fun invoke(): String {
return ""
}
}這種實(shí)現(xiàn)函數(shù)類型的類需要重寫的方法都是invoke(),方法返回值類型對(duì)應(yīng)的就是函數(shù)類型的返回值類型。
這種寫法我在LeakCanary的源碼中就看到了應(yīng)用,比如監(jiān)聽Fragment是否銷毀的類AndroidOFragmentDestroyWatcher:

在這里寫下我對(duì)這兩種方式優(yōu)缺點(diǎn)的比較:
1.函數(shù)類型相比較于接口去實(shí)現(xiàn)的優(yōu)點(diǎn)如下:
參數(shù)類型更加直觀
某個(gè)類實(shí)現(xiàn)了函數(shù)類型,能直觀的看到這個(gè)函數(shù)類型需要傳入的參數(shù)有哪些,是什么類型,返回值又是什么類型,而如果實(shí)現(xiàn)了一個(gè)接口,一般大家都習(xí)慣跳轉(zhuǎn)到接口定義的地方看接口方法的實(shí)現(xiàn),所以這一點(diǎn)函數(shù)類型會(huì)更加方便些
檢索更方便
函數(shù)類型需要重寫的方法名一定叫invoke,所以如果我需要看下某個(gè)實(shí)現(xiàn)類對(duì)重寫方法的具體實(shí)現(xiàn)邏輯,直接在當(dāng)前類中搜索invoke關(guān)鍵字定位到這個(gè)方法即可;而如果是一個(gè)接口接口,我得跳轉(zhuǎn)到接口的定義的地方看接口方法名是什么,才能去實(shí)現(xiàn)類中去搜索,所以在這點(diǎn)上函數(shù)類型會(huì)更加方便些
2.函數(shù)類型相比較于接口去實(shí)現(xiàn)的缺點(diǎn)如下:
函數(shù)類型語義性會(huì)比較差:
畢竟定義的接口名一般是和業(yè)務(wù)進(jìn)行綁定的,能大概知道這個(gè)接口是干啥用的,更加清晰直觀,當(dāng)然這個(gè)問題我們可以使用typealias解決,但就會(huì)失去上面參數(shù)類型更加直觀的優(yōu)點(diǎn)
多態(tài)性會(huì)比較差(自己編的,不知道合不合理)
比如如果定義的一個(gè)接口去實(shí)現(xiàn),我們很容易實(shí)現(xiàn)下面這種功能:
fun test(achieve: Achieve) {
if (achieve is Callback) {
//實(shí)現(xiàn)某些邏輯
}
}而如果使用函數(shù)類型去實(shí)現(xiàn)這種邏輯:

看起來是不是很奇怪,而且對(duì)于很多需要重寫的方法簽名都是相同的(方法參數(shù)和返回值都是相同的),根本無法實(shí)現(xiàn)這種功能,具體的看下面一點(diǎn)的描述。
無法實(shí)現(xiàn)多個(gè)相同的函數(shù)類型
業(yè)務(wù)場景中也存在實(shí)現(xiàn)多個(gè)接口,并且接口定義的方法參數(shù)和返回值類型都是相同的,比如下面:
fun interface Callback {
fun response(): String
}
fun interface Callback2 {
fun response2(): String
}
class Achieve2: Callback, Callback2 {
override fun response(): String {
return ""
}
override fun response2(): String {
return ""
}
}如果使用函數(shù)類型根本無法實(shí)現(xiàn)上面的這種多個(gè)接口實(shí)現(xiàn)的功能:

直接進(jìn)行報(bào)錯(cuò)。
總結(jié)
不管是實(shí)現(xiàn)函數(shù)類型還是接口,兩者都各有其優(yōu)缺點(diǎn),大家需要根據(jù)業(yè)務(wù)場景進(jìn)行具體的選擇
到此這篇關(guān)于詳解如何實(shí)現(xiàn)一個(gè)Kotlin函數(shù)類型的文章就介紹到這了,更多相關(guān)Kotlin函數(shù)類型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android基于TextView不獲取焦點(diǎn)實(shí)現(xiàn)跑馬燈效果
這篇文章主要介紹了Android基于TextView不獲取焦點(diǎn)實(shí)現(xiàn)跑馬燈效果,結(jié)合實(shí)例形式分析了Android基于TextView實(shí)現(xiàn)跑馬燈的功能與布局相關(guān)技巧,需要的朋友可以參考下2017-02-02
Android編程實(shí)現(xiàn)簡易彈幕效果示例【附demo源碼下載】
這篇文章主要介紹了Android編程實(shí)現(xiàn)簡易彈幕效果,涉及Android動(dòng)畫及視圖動(dòng)態(tài)操作相關(guān)技巧,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下2017-01-01
Android系統(tǒng)對(duì)話框使用詳解(最詳細(xì))
這篇文章主要介紹了Android系統(tǒng)對(duì)話框使用詳解(最詳細(xì)),需要的朋友可以參考下2017-10-10
Android位圖(圖片)加載引入的內(nèi)存溢出問題詳細(xì)解析
Android在加載大背景圖或者大量圖片時(shí),常常致使內(nèi)存溢出,下面這篇文章主要給大家介紹了關(guān)于Android位圖(圖片)加載引入的內(nèi)存溢出問題的相關(guān)資料,需要的朋友可以參考下2022-12-12
Android中的Handler與多線程應(yīng)用實(shí)例
這篇文章主要介紹了Android中的Handler與多線程應(yīng)用實(shí)例,本文首先解釋一下handler是用來干嘛的,然后通過例子介紹其在多線程中的應(yīng)用,需要的朋友可以參考下2015-03-03
Android程序開發(fā)之使用PullToRefresh實(shí)現(xiàn)下拉刷新和上拉加載
這篇文章主要介紹了Android程序開發(fā)之使用PullToRefresh實(shí)現(xiàn)下拉刷新和上拉加載的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07

