首页 Kotlin学习笔记(11) - 嵌套类/枚举类/inline value class
文章
取消

Kotlin学习笔记(11) - 嵌套类/枚举类/inline value class

一、嵌套类/内部类

1. 嵌套类

  • 嵌套类不能访问外部成员
  • 与java的静态内部类相似
1
2
3
4
5
6
7
8
class Outer {
    private val bar: Int = 1
    class Nested {
        fun foo() = 2
    }
}

val demo = Outer.Nested().foo() // == 2

还可以进行类与接口的任意嵌套,有助于更好的组织逻辑,提高代码可维护性。

1
2
3
4
5
6
7
8
9
interface OuterInterface {
    class InnerClass
    interface InnerInterface
}

class OuterClass {
    class InnerClass
    interface InnerInterface
}

2. 内部类

使用inner进行修饰,表示为内部类

  • 可访问外部成员
1
2
3
4
5
6
7
8
class Outer {
    private val bar: Int = 1
    inner class Inner {
        fun foo() = bar
    }
}

val demo = Outer().Inner().foo() // == 1

3. 匿名内部类

匿名内部类实例是使用对象表达式(Object Expression)创建

  • 访问外部成员时使用this@OuterClass来引用外部类的实例
  • 可访问外部的局部变量,但必须是val(只读的)
1
2
3
4
5
6
window.addMouseListener(object : MouseAdapter() {

    override fun mouseClicked(e: MouseEvent) { ... }

    override fun mouseEntered(e: MouseEvent) { ... }
})

二、枚举类

1. 声明

与java相同,每个枚举常量都是一个对象,以逗号分隔

1
2
3
4
5
6
7
8
9
enum class Direction {
    NORTH, SOUTH, WEST, EAST
}

enum class Color(val rgb: Int) {
    RED(0xFF0000),
    GREEN(0x00FF00),
    BLUE(0x0000FF)
}

2. 枚举匿名内部类

枚举可通过匿名内部类的方式添加或复写基类方法

1
2
3
4
5
6
7
8
9
10
11
enum class ProtocolState {
    WAITING {
        override fun signal() = TALKING
    },

    TALKING {
        override fun signal() = WAITING
    };

    abstract fun signal(): ProtocolState
}

3. 枚举中实现接口

枚举可以实现接口,但不能继承,因为已经隐式的已经继承了Enum类。接口的实现可以在内部统一实现,也可以在每个条目中独立实现。

1
2
3
4
5
6
7
8
9
10
enum class IntArithmetics : BinaryOperator<Int>, IntBinaryOperator {
    PLUS {
        override fun apply(t: Int, u: Int): Int = t + u
    },
    TIMES {
        override fun apply(t: Int, u: Int): Int = t * u
    };

    override fun applyAsInt(t: Int, u: Int) = apply(t, u)
}

4. 枚举中的一些常量/函数

每个枚举都包含name , ordinal属性,表示名称和位置,及以下函数

1
2
3
4
//序列化为指定枚举,如果不存在会报 IllegalArgumentException
EnumClass.valueOf(value: String): EnumClass
//所有枚举元素
EnumClass.entries: EnumEntries<EnumClass> // specialized List<EnumClass>

可以使用 enumValues()enumValueOf() 函数以泛型的方式访问枚举类中的常量:

1
2
3
4
5
6
7
8
9
10
11
enum class RGB { RED, GREEN, BLUE }

inline fun <reified T : Enum<T>> printAllValues() {
    println(enumValues<T>().joinToString { it.name })
  	//1.9.20 添加了enumEntries,后续将逐步替代 enumValues
  	//当前还是实验性功能,使用时需要添加 @OptIn(ExperimentalStdlibApi::class) 注解
  	println(enumEntries<T>().joinToString { it.name })
  
}

printAllValues<RGB>() // prints RED, GREEN, BLUE

三、Inline value class

Inline value class 与 Inline class类似,算事它超集,后续将完全替代掉,都是为了优化类初始化时创建的包装器,造成的额外开销。

1. 声明

使用value关键字进行修饰,使用@JvmInline进行注解,内联类必须在主构造函数中初始化一个属性。

1
2
3
// For JVM backends
@JvmInline
value class Password(private val s: String)
  • 不可以使用===进行比较,因为最终会替换为传进去的值。
  • 当传递对象为null时会失去内联效果
  • 不允许被继承,始终是final
  • 当大量对象需要频繁创建时我们可以考虑Inline value class
本文由作者按照 CC BY 4.0 进行授权

Kotlin学习笔记(10) - 密封类/接口

Kotlin学习笔记(12) - 对象表达式与对象声明