kotlin类继承结构
一、接口类型
1、和java一样:接口使用interface关键字
interface Clickable { fun click() }
2、和java的差异是:接口也允许有默认的实现,java则需要default关键字
interface Clickable { fun click() fun showOff() = println("I'm clickable!") }
这个例子中,要求子类必须实现click函数,但是showOff函数式可选的。
二、抽象类型
1、和java一样:使用abstract关键字
abstract class Animated { abstract fun animate() // 要求子类实现 fun animateTwice() {} // 默认的实现 }
2、和接口一样:不能创建它的实例、本身的类和类中所有的函数默认都是open
3、要求子类实现的函数则前面要加上abstract
三、继承实现方式
1、继承实现的方式要求标明是override,跟java也是类似的,java注解为@Override;但是他们的区别的:kotlin强制要求标明是override, java的注解是可选的
class Button: Clickable { override fun click() = println("I was clicked") }
2、和java一样,也允许继承多个接口(注意是多个接口)
interface Clickable { fun click() fun showOff() = println("I'm clickable!") } interface Focusable { fun setFocus(b: Boolean) = println("I ${if (b) "got" else "lost"} focus.") fun showOff() = println("i'm focusable") } class Button: Clickable, Focusable { override fun click() = println("I was clicked") override fun showOff() { super<Clickable>.showOff() super<Focusable>.showOff() } }
这里Button多继承了两个接口:Clickable 和 Focusable
3、多继承的接口冲突,Clickable 和 Focusable都有默认的实现:showOff;此时如果Button不重写showOff则编译会提示:
error: class 'Button' must override public open fun showOff(): Unit defined in Clickable because it inherits multiple interface methods of it
如2中的例子所示,增加了showOff的继承实现函数;如果要使用父类的某个实现则需要使用:super<对应的父类名称>.父类方法名
这里增加尖括号是因为继承的父类方法名有冲突。如果是多层继承,也可以使用该方式指定使用哪一个父类的实现
四、默认为final的继承方式
1、因为脆弱的基类问题,所以kotlin跟java相反默认都是final
class RichButton: Button() {} // 这里编译时候会报错,提示:error: this type is final, so it cannot be inherited from class RichButton: Button()
上述使用RichButton继承Button,但是提示Button是final,所以如果要继承Button的话则需要将Button改为open的方式
open class Button: Clickable, Focusable { // 这里增加open fun disable() {} override fun click() = println("I was clicked") override fun showOff() { super<Clickable>.showOff() super<Focusable>.showOff() } }
这样子之后,RichButton的继承就可以正常了
2、函数的继承
1中的open class Button 内部有个函数disable, RichButton直接继承则依旧会报类似类继承的错误
class RichButton: Button() { override fun disable() {} } // error: 'disable' in 'Button' is final and cannot be overridden // override fun disable() {}
同理在Button类中的disable方法中增加open即可
五、访问修饰符的意义
六、可见性修饰符
1、和java的差异:java默认是private,kotlin默认是public
2、kotlin增加新的修饰符:internal,表示在模块内部可见。(模块类似于C++中的一个library,一个模块中可能有多个包)
internal open class TalkactiveButton: Focusable { private fun yell() = println("Hey") protected fun whisper() = println("Let's talk!") }
这里将TalkactiveButton 类定义为internal,说明该类是模块中可见;接下去给该类增加扩展函数
fun TalkactiveButton.giveSpeech() {
yell()
whisper()
}
发现会报错,一共3个错误
/* error: 'public' member exposes its 'internal' receiver type TalkactiveButton fun TalkactiveButton.giveSpeech() { error: cannot access 'yell': it is private in 'TalkactiveButton' yell() error: cannot access 'whisper': it is protected in 'TalkactiveButton' whisper() */
1、TalkactiveButton是internal,那么不能将他的扩展函数设置为比internal更宽的访问范围
2、扩展函数不能访问类内部的protect和private;因为private只允许类内部访问,protect只允许类内部和子类访问
3、protected修饰符:java在同一个包中均可访问,kotlin只能在类和子类中访问
4、kotlin的internal修饰符在字节码中被编译为public;所以在java层面,可以访问kotlin的internal类或者同一个包名字的protected成员
七、内部类和嵌套类
下面是嵌套类和内部类在java和kotlin中的对应关系
注意:内部类能够访问外部类的私有属性和方法
class Outer { private val privateVal = 10 // 这里使用的是private inner class Inner { fun getOuterReference(): Outer = this@Outer fun printOuter() = println(this@Outer.privateVal) } } val outer = Outer() val inner = outer.Inner() // 内部类只能通过外部类进行创建,所以要管理好内部类和外部类的生命周期,防止内部类访问外部类崩溃 inner.printOuter()
上述的printOuter 访问了外部类的私有方法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!