Kotlin学习之-5.11 对象表达式和声明
2017-07-05 14:53
155 查看
Kotlin学习之-5.11 对象表达式和声明
有时候我们需要创建一个类的实例,并且扩展或者修改其中的一两个方法,但不想显式地声明一个子类。Java中是使用内部类来处理这种情况,Kotlin则使用对象表达式和对象声明扩展了这种概念。对象表达式
创建一个内部类的对象,并且继承某些类型,我们这么写: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 foo() { val adHod = object { var x: Int = 0 var y: Int = 0 } print(adHod.x + adHoc.y) }
注意匿名对象仅可以在局部和私有声明中被用来当做类型。如果使用一个匿名对象作为一个公用方法的返回值或者公用属性的类型,那么方法和属性的真正类型是声明成父类的匿名对象,或者
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 // 不可用,Unresolved reference 'x' } }
和Java中的匿名内部类一样,在对象表达式中的代码可以访问封装它的范围的变量。
fun countClicks(window: JComponet) { var clickCount = 0 var enterCound = 0 window.addMouseListener(object: MouseAdapter() { overfide fun mouseClicked(e: MouseEvent) { clickCount++ } overfide fun mouseEntered(e: MouseEvent) { clickCount++ } }) }
对象声明
单例是一种很有用的设计模式,在Kotlin中让定义单例更加容易:object DataProviderManager { fun registerDataProvider(provider: DataProvider) { } val allDataProviders: Collection<DataProvider> get() = // ... }
这种方式叫作对象声明,并且它总有一个
object关键字。就想变量声明,一个对象声明不是一个表达式,不能用作赋值语句的右值。
要引用这个对象,直接使用对象的名字即可:
DataProviderManager.registerDataProvider( ... )
对象还可以有父类:
object DefaultListener : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { } override fun mouseEntered(e: MouseEvent) { } }
注意:对象声明不能是局部的(例如,不能直接嵌套在函数里),但是可以嵌套在其他对象声明或者非内部类中。
伙伴对象
在一个类中的对象声明可以使用伙伴companion关键字。
class MyClass { companion object Factory { fun create(): MyClass = MyClass() } }
伙伴对象的成员可以简单地使用类名作为描述符来调用:
val instance = MyClass.create()
伙伴对象的名字可以省略,这时使用
Companion关键字来访问:
class MyClass { companion object { } } val x = MyClass.Companion
注意,景观伙伴对象的成员和其他语言中的静态成员很像,但是在运行时他们仍然是实例成员的真正对象,例如,可以实现接口:
interface Factory<T> { fun create(): T } class MyClass { companion object : Factory<MyClass> { override fun create(): MyClass = MyClass() } }
但是,在JVM上如果是用
@JvmStatic注解,你仍然可以让伙伴对象的成员生成真正的静态方法和成员。 详见Java interoperability
对象表达式和声明的语法区别
在对象表达式和对象声明之间有一个重要的语法区别:对象表达式在使用的时候,是立即执行的或者立即初始化的
对象声明是延迟初始化地,是在第一次访问对象的时候。
一个伙伴对象是在对应的类加载(或者解析)的时候初始化的,和Java中的静态初始化器对应。
PS,我会坚持把这个系列写完,有问题可以留言交流,也关注专栏Kotlin for Android Kotlin安卓开发
相关文章推荐
- Kotlin学习(八): 对象表达式和声明(Object Expressions and Declarations)
- Kotlin之对象表达式、声明、类代理
- android Kotlin 对象表达式和对象声明
- Kotlin -- 对象表达式和对象声明
- Kotlin基础教程-对象表达式和声明
- (十三)kotlin对象表达式和对象声明
- Kotlin-对象表达式,对象声明及伴随对象
- Kotlin 学习(一)——对象的声明与创建
- Kotlin编程之对象的表达式和声明
- Kotlin语法(十五)-对象表达式和声明
- Kotlin学习之object表达式和声明
- Objective-C学习笔记(十八)——对象方法和类方法的声明,定义及调用
- 栋栋晓12:Javascript学习总结:函数声明和函数表达式的区别,apply和call的区别,
- Kotlin教程学习-伴生对象,getter,setter,内部,局部,匿名类,可变参数
- Kotlin教程学习-函数定义,变量声明
- Javascript学习笔记之 函数篇(一) : 函数声明和函数表达式
- 轻松学习JavaScript十四:JavaScript的RegExp对象(正则表达式)
- C++ Primer 学习笔记12 函数(return语句、函数声明、局部对象、内联函数、类的成员函数、重载函数)
- javaScript的函数(Function)对象的声明(@包括函数声明和函数表达式)
- 正则对象与正则表达式的基础学习