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 访问了外部类的私有方法

 

posted @   LCAC  阅读(265)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
点击右上角即可分享
微信分享提示