15:kotlin 类和对象 -- 函数式接口(Functional (SAM) interfaces)

只有一个抽象方法的接口被称为函数接口,或者称为单一抽象方法(SAM)接口。函数接口可以有多个非抽象成员,但只能有一个抽象成员。

fun interface KRunnable {
   fun invoke()
}

SAM转换

对于函数接口,你可以使用SAM转换来通过lambda表达式使你的代码更简洁、可读

与手动创建实现函数接口的类不同,你可以使用lambda表达式。通过SAM转换,kotlin可以将任何与接口的单一方法签名匹配的lambda表达式转换为代码,动态实例化接口实现。

函数接口

fun interface IntPredicate {
   fun accept(i: Int): Boolean
}

非SAM转换方式实现

val isEven = object : IntPredicate {
    override fun accept(i: Int): Boolean {
        return i % 2 == 0
    }
}

fun main() {
    println(isEven.accept(7))
}

使用SAM转换方式实现

val isEven = IntPredicate { it % 2 == 0 }

fun main() {
    println(isEven.accept(7))
}

lambda表达式可以替换所有非必要的代码

从带有构造函数的接口转移到函数式接口

1.6.20版本开始,kotlin支持对函数接口构造函数的可调用引用,这为从具有构造函数功能的接口迁移到函数接口提供了一种兼容的方式

对于旧代码

interface Printer {
    fun print()
}

// 当前方法定义了带有一个参数(类型为函数类型)的函数,用于创建实现了Printer接口的匿名类的实例
fun Printer(block: () -> Unit): Printer = object : Printer { override fun print() = block() }


fun main() {
    Printer{ print("打印日志") }.print()
}

启用了对函数接口构造函数的可调用引用后

fun interface Printer {
    fun print()
}

fun main() {
    Printer{ print("打印日志") }.print()
}

它的构造函数将会隐式创建,并且使用::Printer函数引用的任何代码都将编译通过

fun interface Printer {
    fun print()
}

fun main() {
    print(::Printer)    // fun interface com.example.Printer
}

通过使用 @Deprecated 注解和 DeprecationLevel.HIDDEN,保留对旧函数 Printer 的二进制兼容性

fun interface Printer {
    fun print()
    
    @Deprecated(message = "Your message about the deprecation", level = DeprecationLevel.HIDDEN)
    fun Printer(block: () -> Unit): Printer = object : Printer { override fun print() = block() }
}

函数接口和类行别名

也可以通过使用函数类型的类型别名来简单地重写上述代码

对于

fun interface IntPredicate {
   fun accept(i: Int): Boolean
}
val isEven = IntPredicate { it % 2 == 0 }

fun main() {
    println(isEven.accept(7))
}

使用类型别名实现

typealias IntPredicate = (i: Int) -> Boolean

val isEven: IntPredicate = { it % 2 == 0 }

fun main() {
    println(isEven(7))
}

函数接口和类型别名有不同的用途。类型别名只是现有类型的名称,它们不创建新的类型(typealias IntPredicate = (i: Int) -> Boolean中,IntPredicate 只是 (i: Int) -> Boolean函数类型的别名,没有创建新的数据类型),而函数接口则会创建新的类型。可以为特定的函数接口提供扩展,以使其对普通函数或其类型别名不适用。

类型别名只能有一个成员,而函数接口可以有多个非抽象成员和一个抽象成员。函数接口还可以实现和扩展其他接口。

函数接口比类型别名更灵活,提供更多功能,但它们在语法和运行时方面可能更麻烦,因为它们可能需要转换为特定的接口。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值