一、嵌套类/内部类
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