Kotlin系列之对象表达式

今天学习一下Kotlin中的对象表达式。

对象表达式,是一种代替Java中的匿名内部类的方法。下面看看具体的用法,以及它与Java匿名内部类之间的区别。

代替Java匿名内部类

我们都知道Java的匿名内部类,这里给一个最简单的匿名内部类的Java代码示例:

1
2
3
4
5
6
String[] fileList  = new File("./").list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return false;
}
});

那上面的匿名内部类在Kotlin中应该怎么写呢,就是使用object关键字来进行编写,基本结构与Java匿名内部类还是非常相似的,代码示例如下:

1
2
3
4
5
6
7
8
9
val fileList = File("./").list(
object: FilenameFilter {

//重写其中的方法
override fun accept(dir: File?, name: String?): Boolean {
return false
}
}
);

你会发现上面的用法跟匿名内部类非常像,当然其实上面的代码还是可以被优化的,只是这里特意写成这样来说明问题。

实现多个接口

在Java中匿名内部类智能只能继承一个类或者实现一个接口,而Kotlin的匿名对象可以实现多个接口或者不实现接口。

1
2
3
4
5
6
7
//匿名内部类实现了FilenameFilter接口
String[] fileList = new File("./").list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return false;
}
});

可以看出上面的Java代码匿名内部类实现了FilenameFilter这个接口,并且只能实现一个。但是Kotlin却没有这个限制。代码示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface A{
fun aTest()
}

interface B{
fun bTest()
}

//对象表达式实现多个接口
val myObj: Any = object : A, B{
override fun bTest() {

}

override fun aTest() {

}
}

同时上面的示例也可以看出,当我们的一个对象表达式的实例需要反复使用时,我们可以给该实例分配一个名字。

访问局部变量

我们知道在Java中,被匿名内部类访问的变量必须被final修饰符修饰。代码示例如下:

1
2
3
4
5
6
7
8
9
10
11
private void Example(Window window){
int i = 0;
window.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
//错误,i必须声明为final的
i++;
}
});
}

而在Kotlin中没有这种限制,对象表达式可以直接访问创建它的函数内部的变量,并且修改其值。同样是上面的例子我们看看Kotlin中的代码例子:

1
2
3
4
5
6
7
8
9
10
private fun Example(window: Window) {
var i = 0
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent?) {
super.mouseClicked(e)
//i的值可以被正常修改
i++
}
})
}

看出上面Kotlin中i的值可以被正常修改不会报错。

写在最后

今天的对象表达式的知识点其实是object关键字的用法之一,它的出现可以很好地帮我们解决一些Kotlin编程中的特殊场景的问题。

如果博客对您有帮助,不妨请我喝杯咖啡...