Kotlin中的函数式接口

557 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情

Kotlin中的函数式接口

在Android中使用Kotlin中看到过类似view.setOnClickListener{}或者view.setOnLongClickListener{}的代码,我们通过查看源码会发现,他就是一个单一的接口就扣包含一个抽象方法

public interface OnClickListener {
    void onClick(View v);
}

那么为什么我们可以使用Kotlin中的Lambda来进行接口实现?这种语法并不是Kotlin中的扩展方法,而是Kotlin中的SAM转换的语法特性。

SAM单一抽象接口

SAM描述的是单一的抽象方法接口,也被称为功能接口。功能接口只能包含一个一个方法。比如我们的Runnable接口,只包含一个run方法,在 Android 中SDK 我们有 OnClickListener, OnLongClickListener ...等。

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}
我们如何创建自定义功能接口?

在Java中如果需要声明一个函数式接口,就只需要创建一个普通接口。然后再接口中创建一个抽象方法

public interface FunInterface {
    void method();
}

Kotlin中的函数式接口还能这样定义

fun interface FunInterface {
    fun method()
}

这样我们就可以在Kotlin中使用函数式接口作为参数传递

fun learnFunInterface(fi : FunInterface) { ... }
怎么去使用函数式接口

在使用该函数的时候,如果是Java或者Kotlin调用,我们可以普通的实现方式是使用匿名内部类的方式进行实现

learnFunInterface(object : FunInterface { 
    override fun method() {
        println("Hello") 
    } 
})

但是因为它是函数式接口,我们就能使用SAM转换,使用Lambda{}来进行传递,这就是所谓的SAM转换

learnFunInterface ({ println("Hello") })

上面的写法并不是最简便,清晰的,Kotlin中规定如果最后一个参数是函数,那么我们可以将lambda移除括号中

learnFunInterface { println("Hello") }

通过上面的了解我们是不是就可以很清楚的知道view.setOnclickListener{}是为什么直接能接收一个Lambda了吗