美文网首页
kotlin语言学习08 ——kotlin接口类、抽象类、伴生对

kotlin语言学习08 ——kotlin接口类、抽象类、伴生对

作者: LiangLliu | 来源:发表于2019-12-24 15:52 被阅读0次

    本小节主要介绍kotlin接口类、抽象类、伴生对象的相关知识。

    1、kotlin的接口

    在Java中,从jdk8开始,Java的接口中可以有默认方法的实现。kotlin的接口与Java相似。

    1.1、kotlin定义接口,关键字Interface

    interface A {
        fun method()
    }
    

    kotlin 接口类中的方法可以实现,也可以不实现。

    interface A {
        // 加上 花括号就可以实现,不加就不实现
        fun method() {
            println("A")
        }
    }
    

    1.2、kotlin接口类的实现

    interface A {
        // 加上 花括号就可以实现,不加就不实现
        fun method() {
            println("A")
        }
    }
    

    下面是对接口的实现。

    class C : A {
        // 方法重写
        override fun method() {
            println("C")
        }
    }
    

    1.3、kotlin接口的实现和继承相同名称的方法

    在kotlin中,当接口的名字和要继承类中有相同方法名时,kotlin使用 super<Class>.method() 来区分两个不同类中的方法。

    // 接口类
    interface A {
        // 加上 花括号就可以实现,不加就不实现
        fun method() {
            println("A")
        }
    }
    
    // 普通类
    open class B {
        open fun method() {
            println("B")
        }
    }
    

    以上类中窜在相同的方法名,此时:

    /**
     * C 继承了B,并实现了 A,里面都有method方法,比较混乱,所以必须要明确使用的那个方法
     *
     * 拥有签名的相同的方法,必须明确,使用 super<Class>.method()
     */
    class C: A,B() {
        override fun method() {
            println("C")
            super<A>.method()
            super<B>.method()
        }
    }
    

    2、kotlin中的抽象类

    kotlin中的抽象类和Java中的抽象类基本上类似。 使用 abstract 关键字进行修饰

    /**
     * 抽象类
     */
    open class BaseClass {
        open fun baseMethod() {
    
        }
    }
    
    abstract class ChildCLass: BaseClass() {
    
    }
    

    3、kotlin的伴生对象

    3.1、对象声明

    在Java送使用 new 关键字,将对象创建出来并且放在内存中。但是在kotlin中可以直接声明一个对象,使用object关键字。

    // 使用object关键字声明一个对象,叫 MyObject
    object MyObject {
        fun method() {
            println("method")
        }
    }
    

    上面对象中的方法可以直接被调用。

    fun main() {
        // 可以直接调用
        MyObject.method() // method
    }
    

    3.2、伴生对象

    补充:

    • 在Java中,static关键字:一个类被static修饰后,那么这个类就可以通过类名直接被调用,这也是Java鼓励的一种调用方式。
    • 我们可以吧Java中的static的方法当做一种全局方法,但是在kotlin中 没有static的方法。
    • 在大多数情况下,kotlin推荐的做法是使用 包级别 的函数作为静态方法。
    • 所以,kotlin会将包级别的函数当做静态方法来看。

    companion object : 伴生对象
    伴生对象: 随着类的存在而存在,相当于实现了Java中的 static 方法,在kotlin中使用 companion关键字来修饰。

    class MyTest() {
        /**
         * 定义类(伴生对象)
         *  MyObject伴随 MyTest 类而存在
         *
         *  @MyObject :类似于重命名,作用不大,可以省略
         *  kotlin中提供了默认的名字 Companion
         */
        companion object MyObject {
            val A: Int = 100;
    
            @JvmStatic
            fun method() {
                println("this is companion object")
            }
        }
    }
    

    伴生对象和 static对象的关系:

    • kotlin中将 MyObject类以MyTest的内部类的方式而存在。
    • 注意: 虽然伴生对象的成员看似是Java中的静态成员,但是在运行期,他们依旧是真实对象的实例对象
    • 在Java上,kotlin可以使用让伴生对象成为真正的静态方法与属性,使用 @JvmStatic 注解来实现
    • 伴生对象在编译后会生成一个静态内部类 (可以通过反编译实现)

    3.3、反编译伴生对象类

    下面通过反编译的方式展示kotlin的伴生对象与Javastatic修饰类的关系。
    使用javap命令反编译上面的kotlin编译后生成的字节码:

    Compiled from "ObjectDeclaration.kt"
    public final class com.liang.kotlin.classAndObject.MyTest {
      public static final com.liang.kotlin.classAndObject.MyTest$MyObject MyObject;
      public com.liang.kotlin.classAndObject.MyTest();
      static {};
      public static final int access$getA$cp();
      public static final void method();
    }
    

    关于kotlin反编译的知识,可以看我之前的教程,点这里
    通过上面反汇编出来的内容我们看到了类的结构,就是Java中的 static 修饰的类,进一步看该类的详细内容:

    Compiled from "ObjectDeclaration.kt"
    public final class com.liang.kotlin.classAndObject.MyTest {
      public static final com.liang.kotlin.classAndObject.MyTest$MyObject MyObject;
    
      public com.liang.kotlin.classAndObject.MyTest();
        Code:
           0: aload_0
           1: invokespecial #8                  // Method java/lang/Object."<init>":()V
           4: return
    
      static {};
        Code:
           0: new           #39                 // class com/liang/kotlin/classAndObject/MyTest$MyObject
           3: dup
           4: aconst_null
           5: invokespecial #44                 // Method com/liang/kotlin/classAndObject/MyTest$MyObject."<init>":(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
           8: putstatic     #37                 // Field MyObject:Lcom/liang/kotlin/classAndObject/MyTest$MyObject;
          11: bipush        100
          13: putstatic     #20                 // Field A:I
          16: return
    
      public static final int access$getA$cp();
        Code:
           0: getstatic     #20                 // Field A:I
           3: ireturn
    
      public static final void method();
        Code:
           0: getstatic     #37                 // Field MyObject:Lcom/liang/kotlin/classAndObject/MyTest$MyObject;
           3: invokevirtual #41                 // Method com/liang/kotlin/classAndObject/MyTest$MyObject.method:()V
           6: return
    }
    

    相关文章

      网友评论

          本文标题:kotlin语言学习08 ——kotlin接口类、抽象类、伴生对

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