Skip to content

Latest commit

 

History

History
180 lines (142 loc) · 4.7 KB

抽象类、嵌套类、内部类、密封类、枚举类.md

File metadata and controls

180 lines (142 loc) · 4.7 KB

抽象类、嵌套类、内部类、密封类、枚举类

抽象类

声明为 abstract 的类内部可以包含没有实现体的成员方法,且该成员方法也用 abstract 标记,这种类称为抽象类,包含的没有实现体的方法称为抽象方法 此外,我们并不需要用 open 标注一个抽象类或者抽象方法,因为这是默认声明的

abstract class BaseClass {
    abstract fun fun1()
}

class Derived : BaseClass() {
    override fun fun1() {
        
    }
}

嵌套类

在 Kotlin 中在类里面再定义的类默认是嵌套类,此时嵌套类不会包含对外部类的隐式引用

class Outer {

    private val bar = 1

    class Nested {
        fun foo1() = 2
        //错误
        //fun foo2() = bar
    }
}

fun main(args: Array<String>) {
    val demo = Outer.Nested().foo1()
}

以上代码通过 IDEA 反编译后可以看到其内部的 Java 实现方式 可以看到 Nested 其实就是一个静态类,因此 foo2() 不能访问外部类的非静态成员,也不用先声明 Outer 变量再指向 Nested 类,而是直接通过 Outer 类指向 Nested 类

public final class Outer {
   private final int bar = 1;

   public static final class Nested {
      public final int foo1() {
         return 2;
      }
   }
}

public final class MainKotlinKt {
   public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      int demo = (new Outer.Nested()).foo1();
   }
}

内部类

如果需要去访问外部类的成员,需要用 inner 修饰符来标注被嵌套的类,这称为内部类。内部类会隐式持有对外部类的引用

class Outer {

    private val bar = 1

    inner class Nested {
        fun foo1() = 2
        fun foo2() = bar
    }
}

fun main(args: Array<String>) {
    val demo = Outer().Nested().foo2()
}

再来看其内部的 Java 实现方式 使用 inner 来声明 Nested 类后,就相当于将之声明为非静态内部类,因此 foo2() 能访问其外部类的非静态成员,在声明 Nested 变量前也需要通过 Outer 变量来指向其内部的 Nested 类

public final class Outer {
   private final int bar = 1;

   public final class Nested {
      public final int foo1() {
         return 2;
      }

      public final int foo2() {
         return Outer.this.bar;
      }
   }
}

public final class MainKotlinKt {
   public static final void main(@NotNull String[] args) {
      Intrinsics.checkParameterIsNotNull(args, "args");
      int demo = (new Outer().new Nested()).foo2();
   }
}
类A在类B中声明 在Java中 在Kotlin中
嵌套类(不存储外部类的引用) static class A class A
内部类(存储外部类的引用) class A inner class A

密封类

Sealed 类(密封类)用于对类可能创建的子类进行限制,用 Sealed 修饰的类的子类只允许被定义在 Sealed 类所在的文件中,这有助于帮助开发者掌握父类与子类之间的变动关系,避免由于代码更迭导致的潜在 bug

例如,对于 View 类,其子类只能定义在与之同一个文件里,Sealed 修饰符修饰的类也隐含表示该类为 open 类,因此无需再显式地添加 open 修饰符

sealed class View {

    fun click() {

    }

}

class Button : View() {

}

class TextView : View() {

}

因为 Sealed 类的子类对于编译器来说是可控的,所以如果在 when 表达式中处理了所有 Sealed 类的子类,那就不需要再提供默认分支

fun check(view: View): Boolean {
    when (view) {
        is Button -> {
            println("is Button")
            return true
        }
        is TextView -> {
            println("is TextView")
            return true
        }
    }
}

枚举类

Kotlin 也提供了枚举的实现,相比 Java 需要多使用 class 关键字来声明枚举

enum class Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}

枚举可以带有参数

enum class Day(val index: Int) {
    SUNDAY(0), MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6)
}

枚举也包含一些函数

fun main(args: Array<String>) {
    val day = Day.FRIDAY
    //获取值
    val value = day.index  //5
    //通过 String 获取相应的枚举值
    val value1 = Day.valueOf("SUNDAY") //SUNDAY
    //获取包含所有枚举值的数组
    val value2 = Day.values()
    //获取枚举名
    val value3 = Day.SUNDAY.name //SUNDAY
    //获取枚举声明的位置
    val value4 = Day.TUESDAY.ordinal //2
}