对象表达式
Kotlin中取消了匿名内部类这个功能,Java中匿名内部类缺点:只能指定一个父类型(接口或者父类)提供了一个更强大的语法:对象表达式来替代匿名内部类,可以指定0~N个父类型(接口或者父类);
对象表达式除了不能有构造器、嵌套类外,支持其他任何成员;
语法:
object(关键字)[:0-N个父类型(类或者接口)]{
//类体部分
//初始化块
//属性
//方法
//内部类
}
- 对象表达式不能是抽象类,因为系统创建对象表达式时就会立即创建对象
- 不能定义构造器,因为其没有类名,可以有初始化块
- 可以包含内部类(非静态内部类),不能包含嵌套类(静8态内部类)
对象表达式较java匿名内部类增强之处:
-
可以不用指定父类型也可以指定多个父类型,匿名内部类时必须指定一个(有且只有一个)父类型
var ob2 = object { var name: String="wang" init { // name = "lelske" } fun test(){ } } Log.d("TAG",ob2.name) ob2.test()
对象表达式可以不用指定父类型,匿名类是做不到的;2)匿名类新增加的方法、属性几乎无法直接访问,但对象表达式则直接可以通过匿名对象的赋值给的引用变量调用其方法、属性;
注意:这里赋值变量类型没有指定,才能调用其新增的方法;如果是var ob2:Any=…形式,将不能调用其新增的方法(应为这里就相当于前面说的多态将子类对象赋值给父类引用变量)
Kotlin对象表达式分为两种:
- 第一种:对象表达式在方法、函数局部范围内,或者使用private修饰的对象表达式,编译器可以识别该对象表达式的真实类型:即向上面的ob2变量的真实类型应该是对应匿名内部类的类型,而不是Any类型,就可以调用其对象表达式新增的方法或者属性
- 非private修饰的对象表达式与java匿名内部类相似,编译期只会表达对象表达式当成他所继承父类或接口的类型,如果没有父类型,就把他当做Any类型;
- 当对象表达式作为某个方法或者函数的返回值(单表达式形式,即不用指定方法返回值类型),该方法是private的,返回的对象表达式就可以识别其真实类型,否则,当做父类型或者接口类型,如果没有指定父类型,就当做Any类型
如:
class ObjectExprType{
private val ob=object{
val name:String="leslie"
}
internal val ob2=object{
val name:String="lin"
}
private fun test()=object{
val name:String="lu"
}
fun testObject(){
//由于ob是private修饰,所以可以识别该对象表达式的真实类型,故可以调用该表达式新增的属性
println(ob.name)
//由于ob2不能识别其真实类型,相当于ob2:Any=obejct{}(多态),故不能调用其新增的属性
println(ob2.name)
}
test().name//由于test()方法是private方法,故返回的对象表达式可以识别真实类型
}
还有一点就是:java中要求匿名内部类访问局部变量时,局部变量必须final修饰,就是说该局部变量不能别被修改,而Kotlin中可以修改该局部变量;
对象表达式较Java中匿名内部类增强总结:
- 对象表达式可以指定0~N个父类型
- Kotlin编译器能更准确的识别局部范围内、private修饰的对象表达式的的真实类型
- 对象表达式可以访问或修改其所在范围内的局部变量