对象表达式和对象声明的作用:我们需要对一个类进行轻微改动后使用时我们不用显示的声明类的子类,这在Java中使用匿名内部类处理,kolin中使用对象表达式和对象声明处理
一:对象表达式
1.1:要创建一个对象表达式,一般是创建一个继承自某一类的匿名类的对象,使用关键字object
interface IDataCallBack{
fun onData(data: String)
}
fun main() {
test(object : IDataCallBack{ //这里创建一个表达式对象,类似Java张的匿名内部类
override fun onData(data: String) {
println(data)
}
})
}
fun test(iDataCallBack: IDataCallBack) {
println("tian")
iDataCallBack.onData("song")
}
1.2:如果超类有构造函数,则必须传递适当的构造参数,多个超类用逗号隔开。
open class A(x: Int){
pubic open val y : Int = x
}
val test: A = object: A(2), IDataCallBack{ //这里的对象表达式继承自多个超类
}
1.3: 有时候我们只需要一个对象,并不需要单独去声明这个类,而且这个对象也没有超类
fun foo(){
val test = object{
var x : Int = 0
var y:Int = 0
}
println(test.x + test.y)
}
注意:匿名对象可以用作只在本地和私有作用域中声明的类型,如果你使用匿名对象作为公有函数返回值或者公有属性,那么实际的类型就是匿名类的超类,如果没有超类则类型是Any
class C {
private fun foo(): object {
val x: String = "x
}
fun publicfoo():object {
val x:String = "x"
}
fun bar(){
val x1 = foo().x //私有作用域访问没问题
val x2 = publicfoo().x //公有函数未能解析到x
}
}
1.4:对象表达式代码可以访问包含它的作用域的变量
fun countClicks() {
valr clickCount = 0
window.addMouseListener(object: MouseAdapter(){
override fun mouseClicked(e: MouseEvent){
clickCount++
}
}
}
二:对象声明
它总是在object关键字之后跟一个名称,就像变量声明一样,它不是一个对象表达式,对象声明的初始化过程是线程安全的。
object DataManager{ //对象声明,
fun register(s: String){}
}
//对象声明后的使用可以直接调用,就好像使用变量一个
DataManager.register()
object DefaultListener: Listener(){} //有超类型指定超类型。
注意:对象声明不能用在局部作用域,但是能嵌套到其他对象声明或非内部类中,
三:伴生对象
3.1:使用
伴生对象作用是在其外部类模拟静态成员,因为kotlin没有Java的static关键字,所以提供了该功能,使用:使用companion关键字修饰对象声明
class MyClass{
companion object Factory { //这里Factory为伴生对象名,可以省略
fun create() = MyClass()
}
}
//伴生对象成员类似Java的静态成员,可以使用外部类名直接调用
val my = MyClass.create()
注意:伴生对象虽然和Java static成员类似但是它是模拟的static成员,伴生对象成员不属于外部类成员
四:差异
- 对象表达式是在使用他们的地方立即初始化
- 对象声明是第一次访问到延迟初始化
- 伴生对象的初始化是在类被加载解析时,与Java静态初始化器语义匹配