本文鏈接
本文結(jié)合自己的感受,做一下簡單的翻譯。原文作者也是《Kotlin for Android developer》的作者。此譯文供大家學(xué)習(xí)參考之用。
Kotlin中的接口,誰說接口不能有實(shí)現(xiàn)代碼
相比Java,用Kotlin寫的接口允許你復(fù)用更多代碼。理由很簡單:你可以加實(shí)現(xiàn)代碼到接口中。如果你在Java8中嘗試,也是類似的。在接口中加實(shí)現(xiàn)代碼是一件不錯的事情,這是你能使用更多強(qiáng)大的代碼組合方式。然后我們接下去看看。
Java 6中的接口
Java接口的問題是我們只能定義描述行為,但是不能有實(shí)現(xiàn)。很多的時候,這夠了,但是如果我們要達(dá)到更好的組合方式,由于強(qiáng)制我們把接口的實(shí)現(xiàn)委托給實(shí)現(xiàn)對象,這些情況不能解決。這樣使得本來簡單組合一下可重用代碼片段就能解決的問題,變的復(fù)雜化了。
Kotlin中使用接口
Kotlin帶給我們一些好消息:接口可以有實(shí)現(xiàn)代碼。這個意味著我們能實(shí)現(xiàn)一種類的多重繼承(有些例子中有部分限制)。我們能讓一個類實(shí)現(xiàn)幾個接口,從每個接口繼承行為(有實(shí)現(xiàn)代碼)。(Java中的類不能多重繼承類,這是一個很大的限制)
寫一些有方法實(shí)現(xiàn)的接口,你不需要做任何特別的:
interface Interface1 {
fun function1() {
Log.d("Interface1", "function1 called")
}
}
我們有另外一個接口2實(shí)現(xiàn)了其他方法:
interface Interface2 {
fun function2() {
Log.d("Interface2", "function2 called")
}
}
有一個類都實(shí)現(xiàn)了他們沒有問題:
class MyClass : Interface1, Interface2 {
fun myFunction() {
function1()
function2()
}
}
好,當(dāng)組織我們代碼的時候,這給我們更多的多樣性。
接口不能持有狀態(tài)
這在思考代碼時候有一個重要的限制。我們能有實(shí)現(xiàn)代碼但是沒有狀態(tài)。這意味著我們不能創(chuàng)建一個屬性,然后用它存儲狀態(tài)。如果我們在接口中定義了一個屬性,這個類實(shí)現(xiàn)了它就必須重寫這個屬性。(你可以定義這個屬性在接口中,但是實(shí)現(xiàn)類必須重寫,本質(zhì)是定義一個該屬性的get方法)
讓我們看一個例子。想象一下這個接口需要上下文:
interface Toaster {
val context: Context
fun toast(message: String) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
}
}
這個代碼很簡單。這個接口有一個實(shí)現(xiàn)的方法用來顯示一個Toast。 它需要一個上下文來做這些事情。如果我們有一個Activity要用這個接口,需要重寫這個上下文:
class MyActivity : AppCompatActivity(), Toaster {
override val context = this
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
toast("onCreate")
}
}
簡單的,我們設(shè)置這個Activity 自己作為上下文,這個接口就使用它。 現(xiàn)在你可以在這個Activity 使用Toaster 函數(shù)沒有任何問題。
接口委托
在Kotlin中另外的非常有趣的特性是接口委托。這個是非常強(qiáng)大的工具讓你能實(shí)現(xiàn)一個更干凈的代碼組合。想象你有一個類C,組合了類A和B的2個對象:
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ù)。如果一個對象是組合自它們的組件,那它就可以直接的使用它們的函數(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)(個人理解是一個繼承轉(zhuǎn)化為組合的方式)。使用接口委托,這個類能直接使用被實(shí)現(xiàn)類的函數(shù),并且包括使用其他對象委托實(shí)現(xiàn)。
總結(jié)
我們看到了Java和Kotlin接口的不同之處?,F(xiàn)在試著找出簡單的解決方式,這些新的方式打開了許多世界的可能。你們的代碼會比之前有更多的復(fù)用性,以及更好的可讀性。