Kotlin中的接口,誰說接口不能有實(shí)現(xiàn)代碼

本文鏈接
本文結(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ù)用性,以及更好的可讀性。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容