class Demo {
val field: String = "demo field"
// kotlin 定义伴生对象
companion object {
// kotlin 定义常量
const val KEY_NAME = "key_name"
// kotlin 模拟静态方法
@JvmStatic // 加注解实现和 java 中使用静态方法相同效果
fun method() {
println("invoke companion method")
}
}
}
fun main() {
// kotlin 可以使用外部类的类名直接调用伴生对象的属性或方法
Demo.KEY_NAME
Demo.method()
}
fun main() {
// 使用 object 声明对象表达式
val runnable = object : Runnable {
override fun run() {
println("run in Runnable")
}
}
// 同上,lambda 简写形式
val runnable2 = Runnable {
println("run in Runnable lambda")
}
// 使用对象表达式
Thread(runnable).start()
Thread(runnable2).start()
// 调用单例类的属性和方法
println(DemoManager.field)
DemoManager.method()
}
/**
* 使用 object 定义单例类
*/
object DemoManager {
var field = "string value"
fun method() {
println("invoke method")
}
}
enum class Week(val text: String = "") {
Monday("星期一"),
Tuesday("星期二"),
Wednesday("星期三"),
Thursday("星期四"),
Friday("星期五"),
Saturday("星期六"),
Sunday("星期日")
}
fun main() {
// 构造枚举
val tuesday = Week.valueOf("Tuesday")
// 访问枚举常量的名称,与在其枚举声明中声明的完全相同。
println(tuesday.name) // Tuesday
// 返回此枚举常量的序数(它在枚举声明中的位置,其中初始常量被分配零序数)
println(tuesday.ordinal) // 1
// 返回此枚举类型的常量的数组
println(Week.values().contentToString()) // [Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday]
// 访问枚举
val week: Week = Week.Monday
when (week) {
Week.Monday -> println(week.name) // Monday
Week.Tuesday -> println(week.name)
Week.Wednesday -> println(week.name)
Week.Thursday -> println(week.name)
Week.Friday -> println(week.name)
Week.Saturday -> println(week.name)
Week.Sunday -> println(week.name)
}
}
/**
* 定义接口
*/
interface Factory {
fun produce()
}
/**
* 美食工厂,实现工厂的方法
*/
class FoodFactory : Factory {
override fun produce() {
println("生产美食")
}
}
/**
* Agent1 实现了 Factory 接口,但委托给 FoodFactory 去实现
*/
class Agent1(factory: FoodFactory) : Factory by factory
/**
* Agent2 实现了 Factory 接口,但委托给 FoodFactory 去实现,重写了接口定义的方法
*/
class Agent2 : Factory by FoodFactory() {
override fun produce() {
println("Agent2 自己 生产美食")
}
}
fun main() {
// 类委托
val agent1 = Agent1(FoodFactory())
agent1.produce() // 生产美食
val agent2 = Agent2()
agent2.produce() // Agent2 自己 生产美食
}
提供和 ReadOnlyProperty 或 ReadWriteProperty 接口相同签名的方法即可实现属性委托
/**
* 定义属性委托
*/
class FieldDemo {
var name: String by FieldDelegate()
}
/**
* 属性委托类,提供和 ReadOnlyProperty 或 ReadWriteProperty 接口相同签名的方法即可实现属性委托
*/
class FieldDelegate {
private var fieldValue = "default str"
operator fun getValue(thisRef: FieldDemo, property: KProperty<*>): String {
println("获取 ${
thisRef.javaClass.simpleName} 的属性 ${
property.name} 值")
return fieldValue
}
operator fun setValue(thisRef: FieldDemo, property: KProperty<*>, value: String) {
println("设置 ${
thisRef.javaClass.simpleName} 的属性 ${
property.name} 值:$value")
fieldValue = value
}
}
fun main() {
// 属性委托
val fieldDemo = FieldDemo()
fieldDemo.name = "test field delegate" // 设置 FieldDemo 的属性 name 值:test field delegate
println(fieldDemo.name) // 获取 FieldDemo 的属性 name 值
}
- kotlin 在 MapAccessors 类中给 Map 定义了和 ReadOnlyProperty 接口相同签名的方法,可以用于只读属性的委托。
- kotlin 在 MapAccessors 类中给 MutableMap 定义了和 ReadWriteProperty 接口相同签名的方法,可以用于读写属性的委托。
/**
* 只读属性可以委托给 Map
* 类只需要对外暴露 map 即可
*/
class DelegateMap(val map: Map<String, Any?>) {
val key1: Int by map
val key2: String by map
val key3: Boolean by map
}
/**
* 读写属性可以委托给 MutableMap
* 类只需要对外暴露 map 即可
*/
class DelegateMutableMap(val map: MutableMap<String, Any?>) {
var key1: Int by map
var key2: String by map
var key3: Boolean by map
}
fun main() {
// 只读属性对外暴露 Map
val delegate1 = DelegateMap(mapOf("key1" to 1, "key2" to "str", "key3" to true))
// 相当于调用 ReadOnlyProperty 的 getValue 方法
println(delegate1.key1)
println(delegate1.key2)
println(delegate1.key3)
val map = delegate1.map
println(map["key1"])
println(map["key2"])
println(map["key3"])
// 读写属性对外暴露 MutableMap
val delegate2 = DelegateMutableMap(mutableMapOf())
// 相当于调用 ReadWriteProperty 的 setValue 方法
delegate2.key1 = 100
delegate2.key2 = "key2 value"
delegate2.key3 = false
val mutableMap = delegate2.map
println(mutableMap["key1"])
println(mutableMap["key2"])
println(mutableMap["key3"])
}
- 当延迟属性被访问的时候才会执行 lambda 表达式初始化值
- 只会执行一次 lambda 表达式,随后会获取第一次的值直接返回
// 延迟属性:只会获取一次 lambda 表达式的值,后续会使用第一次获取的值直接返回
val lazyField: String by lazy {
println("执行 lambda 表达式")
"this is a lazy field"
}
// 传入策略,使用锁用于确保只有单个线程可以初始化Lazy实例。
val lazyField2: String by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
"this is a lazy field"
}
fun main() {
// 只会打印一次 "执行 lambda 表达式"
println(lazyField)
println(lazyField)
}
/**
* 属性监听,总是能赋值成功
*/
var observerField1: String by Delegates.observable("default") {
property, oldValue, newValue ->
println("$property 的 oldValue: $oldValue, newValue: $newValue")
}
/**
* 属性监听,符合条件 新值大于 0,才能成功赋值
*/
var observerField2: Int by Delegates.vetoable(0) {
property, oldValue, newValue ->
println("$property 的 oldValue: $oldValue, newValue: $newValue")
newValue > 0
}
fun main() {
observerField1 = "set new value" // 打印:kotlin.String 的 oldValue: default, newValue: set new value
observerField2 = 1 // 打印:kotlin.Int 的 oldValue: 0, newValue: 1
observerField2 = -1 // 打印:kotlin.Int 的 oldValue: 1, newValue: -1,此处会设置失败,需要大于0才能设置成功
println(observerField2) // 打印:1
}
Companion&Object&Enum&Delegate&Lazy.kt