对象表达式
通过对象表达式实现一个匿名内部类的对象用于方法的参数中:
window.addMouseListener(object : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { // ... } override fun mouseEntered(e: MouseEvent) { // ... } })
对象可以继承于某个基类,或者实现其他接口:
open class A(x: Int) { public open val y: Int = x } interface B {……} val ab: A = object : A(1), B { override val y = 15 }
如果超类型有一个构造函数,则必须传递参数给它。多个超类型和接口可以用逗号分隔。
通过对象表达式可以越过类的定义直接得到一个对象:
fun main(args: Array<String>) { val site = object { var name: String = "菜鸟教程" var url: String = "www.runoob.com" } println(site.name) println(site.url) }
请注意,匿名对象可以用作只在本地和私有作用域中声明的类型。如果你使用匿名对象作为公有函数的 返回类型或者用作公有属性的类型,那么该函数或属性的实际类型 会是匿名对象声明的超类型,如果你没有声明任何超类型,就会是 Any。在匿名对象 中添加的成员将无法访问。
class C { // 私有函数,所以其返回类型是匿名对象类型 private fun foo() = object { val x: String = "x" } // 公有函数,所以其返回类型是 Any fun publicFoo() = object { val x: String = "x" } fun bar() { val x1 = foo().x // 没问题 val x2 = publicFoo().x // 错误:未能解析的引用“x” } }
在对象表达中可以方便的访问到作用域中的其他变量:
fun countClicks(window: JComponent) { var clickCount = 0 var enterCount = 0 window.addMouseListener(object : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { clickCount++ } override fun mouseEntered(e: MouseEvent) { enterCount++ } }) // …… }
对象声明
Kotlin 使用 object 关键字来声明一个对象。
Kotlin 中我们可以方便的通过对象声明来获得一个单例。
object DataProviderManager { fun registerDataProvider(provider: DataProvider) { // …… } val allDataProviders: Collection<DataProvider> get() = // …… }
引用该对象,我们直接使用其名称即可:
DataProviderManager.registerDataProvider(……)
当然你也可以定义一个变量来获取这个对象,当时当你定义两个不同的变量来获取这个对象时,你会发现你并不能得到两个不同的变量。也就是说通过这种方式,我们获得一个单例。
var data1 = DataProviderManager var data2 = DataProviderManager data1.name = "test" print("data1 name = ${data2.name}")
对象表达式和对象声明之间的语义差异
对象表达式和对象声明之间有一个重要的语义差别:
-
对象表达式是在使用他们的地方立即执行的
-
对象声明是在第一次被访问到时延迟初始化的
-
伴生对象的初始化是在相应的类被加载(解析)时,与 Java 静态初始化器的语义相匹配
kotlin 委托
委托模式是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。
Kotlin 直接支持委托模式,更加优雅,简洁。Kotlin 通过关键字 by 实现委托。
属性委托
属性委托指的是一个类的某个属性值不是在类中直接进行定义,而是将其托付给一个代理类,从而实现对该类的属性统一管理。
属性委托语法格式:
val/var <属性名>: <类型> by <表达式>
- var/val:属性类型(可变/只读)
- 属性名:属性名称
- 类型:属性的数据类型
- 表达式:委托代理类
by 关键字之后的表达式就是委托, 属性的 get() 方法(以及set() 方法)将被委托给这个对象的 getValue() 和 setValue() 方法。属性委托不必实现任何接口, 但必须提供 getValue() 函数(对于 var属性,还需要 setValue() 函数)。
定义一个被委托的类
该类需要包含 getValue() 方法和 setValue() 方法,且参数 thisRef 为进行委托的类的对象,prop 为进行委托的属性的对象。