您好,登錄后才能下訂單哦!
一、首先來看一個例子
package net.println.kotlin.chapter4 /** * @author:wangdong * @description:類實現接口的沖突問題 */ interface B{ fun x(): Int = 1 } interface C{ fun x(): Int = 0 } /**一個類實現了兩個接口,兩個接口中的方法相同,這個類在覆寫的時候就會出現沖突*/ class D: B,C{ //當下面兩個方法同時存在的時候,就會報方法相同的沖突 override fun x(): Int { return super<B>.x() } override fun x(): Int { return super<C>.x() } }
二、解決沖突的例子
package net.println.kotlin.chapter4 /** * @author:wangdong * @description:類繼承類,實現接口的方法沖突問題 * 接口方法可以有默認的實現 * 簽名一致且返回值相同的沖突 * 子類(實現類)必須覆寫沖突方法 * super<[父類(接口)名]>.[方法名]([參數列表]) */ abstract class A{ open fun x(): Int = 5 } interface B{ fun x(): Int = 1 } interface C{ fun x(): Int = 0 } /**一個類實現了兩個接口,兩個接口中的方法相同,這個類在覆寫的時候就會出現沖突*/ /**采用分支模式解決沖突問題*/ class D(var y: Int = 0):A() ,B,C{ //返回值一定要一樣啊,例如:一定要是Int override fun x(): Int { println("call x(): Int in D") if (y > 0){ return y }else if (y < -200){ return super<C>.x() }else if (y < -100){ return super<B>.x() }else{ return super<A>.x() } } } fun main(args: Array<String>) { println(D(3).x()) println(D(-10).x()) println(D(-110).x()) println(D(-230).x()) } /**輸出的結果*/ call x(): Int in D call x(): Int in D call x(): Int in D call x(): Int in D
補充知識:Kotlin 如何優雅的實現『多繼承』
這一期給大家講一個有意思的東西。我們都知道 Java 當年高調的調戲 C++ 的時候,除了最愛說的內存自動回收之外,還有一個著名的單繼承,任何 Java 類都是 Object 的子類,任何 Java 類有且只有一個父類,不過,它們可以有多個接口,就像這樣:
public class Java extends Language implements JVMRunnable{ ... } public class Kotlin extends Language implements JVMRunnable, FERunnable{ ... }
這樣用起來真的比 C++ 要簡單得多,不過有時候也會有些麻煩:Java 和 Kotlin 都可以運行在 JVM 上面,我們用一個接口 JVMRunnable 來標識它們的這一身份;現在我們假設這二者對于 JVMRunnable 接口的實現都是一樣的,所以我們將會在 Java 和 Kotlin 當中寫下兩段重復的代碼:
public class Java extends Language implements JVMRunnable{ public void runOnJVM(){ ... } } public class Kotlin extends Language implements JVMRunnable, FERunnable{ public void runOnJVM(){ ... } public void runOnFE(){ ... } }
重復代碼使我們最不愿意看到的,所以我們決定創建一個 JVMLanguage 作為 Java 和 Kotlin 的父類,它提供默認的 runOnJVM 的實現。看上去挺不錯。
public abstract class JVMLanguage{ public void runOnJVM(){ ... } } public class Java extends JVMLanguage{ } public class Kotlin extends JVMLanguage implements FERunnable{ public void runOnFE(){ ... } }
當然,我們還知道 Kotlin 可以編譯成 Js 運行,那我們硬生生的把 Kotlin 稱作 JVMLanguage 就有些牽強了,而剛剛我們覺得很完美的寫法呢,其實是不合適的。
簡單的說,繼承和實現接口的區別就是:繼承描述的是這個類『是什么』的問題,而實現的接口則描述的是這個類『能做什么』的問題。
Kotlin 與 Java 在能夠運行在 JVM 這個問題上是一致的,可 Java 卻不能像 Kotlin 那樣去運行在前端,Kotlin 和 Java 運行在 JVM 上這個點只能算作一種能力,而不能對其本質定性。
于是我們在 Java 8 當中看到了接口默認實現的 Feature,于是我們的代碼可以改改了:
public interface JVMRunnable{ default void runOnJVM(){ ... } } public class Java extends Language implements JVMRunnable{ } public class Kotlin extends Language implements JVMRunnable, FERunnable{ public void runOnFE(){ ... } }
這樣很好,不過,由于接口無法保存狀態,runOnJVM 這個方法的接口級默認實現仍然非常受限制。
那么 Kotlin 給我們帶來什么呢?大家請看下面的代碼:
abstract class Languageinterface JVMRunnable{ fun runOnJVM() } class DefaultJVMRunnable : JVMRunnable { override fun runOnJVM() { println("running on JVM!") } } class Java(jvmRunnable: JVMRunnable) : Language(), JVMRunnable by jvmRunnable class Kotlin(jvmRunnable: JVMRunnable) : Language(), JVMRunnable by jvmRunnable, FERunnable{ fun runOnFE(){ ... } }
通過接口代理的方式,我們把 JVMRunnable 的具體實現代理給了 jvmRunnable 這個實例,這個實例當然是可以保存狀態的,它一方面可以很好地解決我們前面提到的接口默認實現的問題,另一方面也能在提供能力的同時不影響原有類的『本質』。
以上這篇解決Kotlin 類在實現多個接口,覆寫多個接口中相同方法沖突的問題就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。