本文鏈接
本文結(jié)合自己的感受慨蛙,做一下簡單的翻譯。原文作者也是《Kotlin for Android developer》的作者纪挎。此譯文供大家學(xué)習(xí)參考之用期贫。
Kotlin中的接口,誰說接口不能有實(shí)現(xiàn)代碼
相比Java异袄,用Kotlin寫的接口允許你復(fù)用更多代碼通砍。理由很簡單:你可以加實(shí)現(xiàn)代碼到接口中。如果你在Java8中嘗試烤蜕,也是類似的封孙。在接口中加實(shí)現(xiàn)代碼是一件不錯(cuò)的事情,這是你能使用更多強(qiáng)大的代碼組合方式讽营。然后我們接下去看看虎忌。
Java 6中的接口
Java接口的問題是我們只能定義描述行為,但是不能有實(shí)現(xiàn)橱鹏。很多的時(shí)候膜蠢,這夠了,但是如果我們要達(dá)到更好的組合方式蚀瘸,由于強(qiáng)制我們把接口的實(shí)現(xiàn)委托給實(shí)現(xiàn)對象狡蝶,這些情況不能解決庶橱。這樣使得本來簡單組合一下可重用代碼片段就能解決的問題贮勃,變的復(fù)雜化了。
Kotlin中使用接口
Kotlin帶給我們一些好消息:接口可以有實(shí)現(xiàn)代碼苏章。這個(gè)意味著我們能實(shí)現(xiàn)一種類的多重繼承(有些例子中有部分限制)寂嘉。我們能讓一個(gè)類實(shí)現(xiàn)幾個(gè)接口,從每個(gè)接口繼承行為(有實(shí)現(xiàn)代碼)枫绅。(Java中的類不能多重繼承類泉孩,這是一個(gè)很大的限制)
寫一些有方法實(shí)現(xiàn)的接口,你不需要做任何特別的:
interface Interface1 {
fun function1() {
Log.d("Interface1", "function1 called")
}
}
我們有另外一個(gè)接口2實(shí)現(xiàn)了其他方法:
interface Interface2 {
fun function2() {
Log.d("Interface2", "function2 called")
}
}
有一個(gè)類都實(shí)現(xiàn)了他們沒有問題:
class MyClass : Interface1, Interface2 {
fun myFunction() {
function1()
function2()
}
}
好并淋,當(dāng)組織我們代碼的時(shí)候寓搬,這給我們更多的多樣性。
接口不能持有狀態(tài)
這在思考代碼時(shí)候有一個(gè)重要的限制县耽。我們能有實(shí)現(xiàn)代碼但是沒有狀態(tài)句喷。這意味著我們不能創(chuàng)建一個(gè)屬性镣典,然后用它存儲狀態(tài)。如果我們在接口中定義了一個(gè)屬性唾琼,這個(gè)類實(shí)現(xiàn)了它就必須重寫這個(gè)屬性兄春。(你可以定義這個(gè)屬性在接口中,但是實(shí)現(xiàn)類必須重寫锡溯,本質(zhì)是定義一個(gè)該屬性的get方法)
讓我們看一個(gè)例子赶舆。想象一下這個(gè)接口需要上下文:
interface Toaster {
val context: Context
fun toast(message: String) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
}
}
這個(gè)代碼很簡單。這個(gè)接口有一個(gè)實(shí)現(xiàn)的方法用來顯示一個(gè)Toast祭饭。 它需要一個(gè)上下文來做這些事情芜茵。如果我們有一個(gè)Activity要用這個(gè)接口,需要重寫這個(gè)上下文:
class MyActivity : AppCompatActivity(), Toaster {
override val context = this
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
toast("onCreate")
}
}
簡單的甜癞,我們設(shè)置這個(gè)Activity 自己作為上下文夕晓,這個(gè)接口就使用它。 現(xiàn)在你可以在這個(gè)Activity 使用Toaster 函數(shù)沒有任何問題悠咱。
接口委托
在Kotlin中另外的非常有趣的特性是接口委托蒸辆。這個(gè)是非常強(qiáng)大的工具讓你能實(shí)現(xiàn)一個(gè)更干凈的代碼組合。想象你有一個(gè)類C析既,組合了類A和B的2個(gè)對象:
interface A {
fun functionA(){}
}
interface B {
fun functionB(){}
}
class C(val a: A, val b: B) {
fun functionC(){
a.functionA()
b.functionB()
}
}
類C在自己代碼中使用A和B的函數(shù)躬贡。如果一個(gè)對象是組合自它們的組件,那它就可以直接的使用它們的函數(shù)眼坏。
使用接口委托是另外一種寫法拂玻,結(jié)果和上面一樣的方式:
class C(a: A, b: B): A by a, B by b {
fun functionC(){
functionA()
functionB()
}
}
你能看到類C實(shí)現(xiàn)了A和B,但是它接受作為參數(shù)宰译,對象全部委托實(shí)現(xiàn)(個(gè)人理解是一個(gè)繼承轉(zhuǎn)化為組合的方式)檐蚜。使用接口委托,這個(gè)類能直接使用被實(shí)現(xiàn)類的函數(shù)沿侈,并且包括使用其他對象委托實(shí)現(xiàn)闯第。
總結(jié)
我們看到了Java和Kotlin接口的不同之處。現(xiàn)在試著找出簡單的解決方式缀拭,這些新的方式打開了許多世界的可能咳短。你們的代碼會比之前有更多的復(fù)用性,以及更好的可讀性蛛淋。