解决Kotlin 类在实现多个接口,覆写多个接口中相同方法冲突的问题
一、首先来看一个例子
packagenet.println.kotlin.chapter4 /** *@author:wangdong *@description:类实现接口的冲突问题 */ interfaceB{ funx():Int=1 } interfaceC{ funx():Int=0 } /**一个类实现了两个接口,两个接口中的方法相同,这个类在覆写的时候就会出现冲突*/ classD:B,C{ //当下面两个方法同时存在的时候,就会报方法相同的冲突 overridefunx():Int{ returnsuper.x() } overridefunx():Int{ returnsuper.x() } }
二、解决冲突的例子
packagenet.println.kotlin.chapter4 /** *@author:wangdong *@description:类继承类,实现接口的方法冲突问题 *接口方法可以有默认的实现 *签名一致且返回值相同的冲突 *子类(实现类)必须覆写冲突方法 *super<[父类(接口)名]>.[方法名]([参数列表]) */ abstractclassA{ openfunx():Int=5 } interfaceB{ funx():Int=1 } interfaceC{ funx():Int=0 } /**一个类实现了两个接口,两个接口中的方法相同,这个类在覆写的时候就会出现冲突*/ /**采用分支模式解决冲突问题*/ classD(vary:Int=0):A(),B,C{ //返回值一定要一样啊,例如:一定要是Int overridefunx():Int{ println("callx():IntinD") if(y>0){ returny }elseif(y<-200){ returnsuper.x() }elseif(y<-100){ returnsuper.x() }else{ returnsuper.x() } } } funmain(args:Array ){ println(D(3).x()) println(D(-10).x()) println(D(-110).x()) println(D(-230).x()) } /**输出的结果*/ callx():IntinD callx():IntinD callx():IntinD callx():IntinD
补充知识:Kotlin如何优雅的实现『多继承』
这一期给大家讲一个有意思的东西。我们都知道Java当年高调的调戏C++的时候,除了最爱说的内存自动回收之外,还有一个著名的单继承,任何Java类都是Object的子类,任何Java类有且只有一个父类,不过,它们可以有多个接口,就像这样:
publicclassJavaextendsLanguage implementsJVMRunnable{ ... } publicclassKotlinextendsLanguage implementsJVMRunnable,FERunnable{ ... }
这样用起来真的比C++要简单得多,不过有时候也会有些麻烦:Java和Kotlin都可以运行在JVM上面,我们用一个接口JVMRunnable来标识它们的这一身份;现在我们假设这二者对于JVMRunnable接口的实现都是一样的,所以我们将会在Java和Kotlin当中写下两段重复的代码:
publicclassJavaextendsLanguage implementsJVMRunnable{ publicvoidrunOnJVM(){ ... } } publicclassKotlinextendsLanguage implementsJVMRunnable,FERunnable{ publicvoidrunOnJVM(){ ... } publicvoidrunOnFE(){ ... } }
重复代码使我们最不愿意看到的,所以我们决定创建一个JVMLanguage作为Java和Kotlin的父类,它提供默认的runOnJVM的实现。看上去挺不错。
publicabstractclassJVMLanguage{ publicvoidrunOnJVM(){ ... } } publicclassJavaextendsJVMLanguage{ } publicclassKotlinextendsJVMLanguage implementsFERunnable{ publicvoidrunOnFE(){ ... } }
当然,我们还知道Kotlin可以编译成Js运行,那我们硬生生的把Kotlin称作JVMLanguage就有些牵强了,而刚刚我们觉得很完美的写法呢,其实是不合适的。
简单的说,继承和实现接口的区别就是:继承描述的是这个类『是什么』的问题,而实现的接口则描述的是这个类『能做什么』的问题。
Kotlin与Java在能够运行在JVM这个问题上是一致的,可Java却不能像Kotlin那样去运行在前端,Kotlin和Java运行在JVM上这个点只能算作一种能力,而不能对其本质定性。
于是我们在Java8当中看到了接口默认实现的Feature,于是我们的代码可以改改了:
publicinterfaceJVMRunnable{ defaultvoidrunOnJVM(){ ... } } publicclassJavaextendsLanguage implementsJVMRunnable{ } publicclassKotlinextendsLanguage implementsJVMRunnable,FERunnable{ publicvoidrunOnFE(){ ... } }
这样很好,不过,由于接口无法保存状态,runOnJVM这个方法的接口级默认实现仍然非常受限制。
那么Kotlin给我们带来什么呢?大家请看下面的代码:
abstractclassLanguageinterfaceJVMRunnable{ funrunOnJVM() } classDefaultJVMRunnable:JVMRunnable{ overridefunrunOnJVM(){ println("runningonJVM!") } } classJava(jvmRunnable:JVMRunnable) :Language(),JVMRunnablebyjvmRunnable classKotlin(jvmRunnable:JVMRunnable) :Language(),JVMRunnablebyjvmRunnable,FERunnable{ funrunOnFE(){ ... } }
通过接口代理的方式,我们把JVMRunnable的具体实现代理给了jvmRunnable这个实例,这个实例当然是可以保存状态的,它一方面可以很好地解决我们前面提到的接口默认实现的问题,另一方面也能在提供能力的同时不影响原有类的『本质』。
以上这篇解决Kotlin类在实现多个接口,覆写多个接口中相同方法冲突的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。