美文网首页Kotlin 教程
【Kotlin从入门到深坑】之类的覆盖属性和方法以及抽象类

【Kotlin从入门到深坑】之类的覆盖属性和方法以及抽象类

作者: Android探索之路 | 来源:发表于2017-12-23 22:19 被阅读3次

    简介

    本篇博客主要是介绍Kotlin语法中的【类的覆盖属性和方法以及抽象类】相关的知识,帮助各位更快的掌握Kotlin,如果有疏漏或者错误,请在留言中指正,谢谢。 系列汇总地址


    上一篇博客中我们详细介绍了类的继承和构造,下面我们来讲一下,在继承时如何覆盖方法。


    覆盖方法

    我们先看一下如何去写,例子如下:

    // 父类,使用open关键词
    open class TestB {
       open fun test() { //需要被重写的方法需要使用open修饰
            
        }
    }
    //子类
    class TestA() : TestB() {
        override fun test() {//重写的方法需要使用override
            super.test()
        }
    }
    

    方法和类一样,默认是final的禁止重写的,所以必须加上open修饰,而重写的方法也必须加上override,否则子类不允许相同签名的函数。

    还有一点是需要注意的,默认override的函数是open的,如果你想再次限制它被覆盖,可以使用final修饰,代码如下:

    //子类
    class TestA() : TestB() {
        final override fun test() {//重写的方法需要使用override,使用了final,后续无法覆盖
            super.test()
        }
    }
    
    

    覆盖属性

    我们先看一下如何去写,例子如下:

    //父类
    open class TestB {
    
       open var x: Int? = null //属性x
            get() {//重写了get方法,此处后面详解
                field = 34
                return field
            }
    }
    
    class TestA() : TestB() {
        override var x: Int?=null //它覆盖对应属性后,对应的方法也被覆盖
        
    
    }
    

    对于Kotlin中的属性都有默认的get、set方法,当然也可以重写,比如上面的TestB的x的属性的get方法被重写了。但是TestA 覆盖属性后,TestB中定义的get方法对其无效,举例如下,便于理解其含义:

     var a = TestA()
        println(a.x)
    
        var b=TestB()
        println(b.x)
    

    输出结果:

    null  //说明TestB的get方法对TestA类无效
    34   //说明TestB的get方法对TestB类有效
    

    注意:如果原类型为var,则覆盖类型可以为var,且不可以是val,如果原类型是val,覆盖类型可以是val,也可以是var


    多实现

    在Kotlin中,对于继承来说,如果一个类从它的直接超类继承相同成员的多个实现,它必须覆盖这个成员并提供自己的实现。为了表达�采用从哪个超类型继承实现,我们使用super<父类名>,下面举例说明:

    //首先声明一个类
    open class TestB {
    
       open var x: Int? = null
            get() {
                field = 34
                return field
            }
    
        open fun test() { //此处有一个可以覆盖的方法test()
    
        }
    
    
    }
    
    //声明一个接口
    interface TestC { //这个是接口的声明方式
        var x: Int? //声明了一个抽象字段,实现类必须覆盖此属性
        fun test() { //声明了一个方法,这个是特殊的,可以有实现方法
            print("d")
        }
    
        fun test2() //这个是和java一致的抽象方法
    }
    

    此处需要注意此处的接口是可以实现具体的方法的

    //实现类TestA
    class TestA() : TestC, TestB() {
    
        override fun test2() {//对于一般的抽象方法等同于java中,必须实现,否则声明成抽象类
    
        }
    
        override fun test() {//此处必须写,因为test有两种不同实现
            super<TestC>.test()
            super<TestB>.test()
            //上面两个都可不写,也可以都写,类似于super.method
    
        }
    
        override var x: Int? = null //对于字段没影响,因为接口的属性不允许赋值,
    
    
    }
    

    我们总结一波:

    • 首先继承TestBTestC是正常的
    • 由于TestBTestC内都有test方法,所以TestC必须实现test方法
    • 在子类TestC中使用super<TestB>.test()或者super<TestC>.test() 来调用父类的实现

    上面我们说的是方法,仔细的话,我们还能看到接口还有属性的定义,对于TestBTestC都有x字段,TestA中进行重写的话,get/set都会被覆盖,所以不会出现上面方法的问题

    还需要注意,看一下代码

    open class TestB {//类的一个成员变量
        open var x: Int? = null
    }
    
    interface TestC { //这个是接口的声明方式
        var x: Int? //声明了一个抽象字段,实现类必须覆盖此属性
    
    }
    
    //实现类
    class TestA() : TestC, TestB() {
    }
    

    我们总结一波:

    • 对于接口来说,他的方法默认是抽象的,除非自己实现了
    • 对于接口的成员变量也是一样的,也是默认抽象的,子类必须覆盖
    • 但凡事都有例外,对于上面的实现中,我们并没覆盖x,但仍然正确是,因为,接口只是约束作用,因为TestA继承了TestB,也就有了X,字段,而接口也就是约束必须有该字段即可,所以,上面的实现也是允许的

    抽象类

    类和类中的某些成员可以声明成abstract ,抽象成员在本类中可以不去实现,需要注意的是我们不需要用open标注抽象类或者函数,更有趣的是看如下实现:

    //开放的类和方法
    open class A{
        open fun  test(){
            
        }
    }
    //抽象类
    abstract class B : A() {
        abstract override fun test() //抽象方法覆盖开放方法
    }
    

    我们可以用一个抽象成员去覆盖一个非抽象的开放成员


    伴生对象

    与java不同,Kotlin没有静态方法,官方建议使用包级函数,可以使用如下两种方式来实现类似静态类、静态方法的方式
    第一种:

    object StaticDemo{
        fun test(){
            print("")
        }
    }
    

    使用方法如下:

      StaticDemo.test()
    
    

    第二种:

    class Demo {
        companion object {//声明在内部的,类似静态方法,可以使用 类名.方法名
            fun test() {
                print("")
            }
        }
    
        fun test2() { //test2在外部,必须实例化后才可调用
            
        }
    
    }
    

    使用方法:

      Demo.test()
    

    下面我们总结一波:

    • 无论方法还是类除了抽象类、抽象方法、接口、接口方法外,其他的继承都需要写open,重写的成员变量和方法需要override

    • 与java不同,Kotlin中的接口可以自己实现方法,从而导致了出现多实现的问题,出现多实现的,继承的子类需要重写对应的方法,然后决定是否或者调用哪个父类的方法。


    总结

    至此已经学完了Kotlin的【类的覆盖属性和方法以及抽象类】相关的知识,多回顾多思考,继续后续内容

    相关文章

      网友评论

        本文标题:【Kotlin从入门到深坑】之类的覆盖属性和方法以及抽象类

        本文链接:https://www.haomeiwen.com/subject/jzfcgxtx.html