如何在kotlin中将lambdas与函数式接口一起使用并直接将lambda分配给var
Posted
技术标签:
【中文标题】如何在kotlin中将lambdas与函数式接口一起使用并直接将lambda分配给var【英文标题】:How to use lambdas together with functional interfaces and directly assign lambda to var in kotlin 【发布时间】:2021-06-29 21:07:19 【问题描述】:我有这个代码:
package org.medianik.kotlindoc
fun main()
val creator:Creatable = toCreatable(::Created)// Ok. Compiles, and works fine
val creator1:Creatable = ::Created // Compilation error
val creator2:Creatable = ::Created as Creatable // ok enough to compile, but there is runtime exception
val c = creator.create(5)
val creator3:Creatable = toCreatable(c::doSmth1) // Ok. Compiles, works fine
val creator4:Creatable = c::doSmth1 // Compilation error
val creator5:Creatable = c::doSmth1 as Creatable // Again ok enough to compile, but there is runtime exception
val creator6:Creatable = Creatable i -> Created(i) // Works fine, but that's not what I want
fun toCreatable(c:Creatable) = c
fun interface Creatable
fun create(i: Int) : Created
class Created(private var i: Int)
fun doSmth1(add: Int): Created
return this.also i+=add
creator2 的例外情况:
Exception in thread "main" java.lang.ClassCastException: class org.medianik.kotlindoc.MainKt$main$creator2$1 cannot be cast to class org.medianik.kotlindoc.Creatable (org.medianik.kotlindoc.MainKt$main$creator2$1 and org.medianik.kotlindoc.Creatable are in unnamed module of loader 'app')
creator5 例外:
Exception in thread "main" java.lang.ClassCastException: class org.medianik.kotlindoc.MainKt$main$creator5$1 cannot be cast to class org.medianik.kotlindoc.Creatable (org.medianik.kotlindoc.MainKt$main$creator5$1 and org.medianik.kotlindoc.Creatable are in unnamed module of loader 'app')
我不知道如何使 creator1/4 与方法引用一起工作。有什么方法可以让它们工作吗?因为这对我来说似乎毫无意义:如果您将方法引用作为参数传递给函数——它会转换为接口,否则不会。它是如何工作的?
对于接口的函数是否有一些特殊的转换?
【问题讨论】:
【参考方案1】:我将您的代码复制到 IntelliJ 中,但行中也出现错误
val creator:Creatable = toCreatable(::Created)
val creator3:Creatable = toCreatable(c::doSmth1)
问题是,Creatable
是一个命名接口,它与类 Created
具有相同的方法签名,但这个类没有实现接口。
请注意,即使有签名,函数也不会实现接口。
您可以 decare 函数类型而不是接口。请注意,这并不相同,但它们的处理方式几乎相同。
typealias Creatable = (Int) -> Created
或者您可以编写一个接受此类函数类型的包装器:
fun toCreatable(c:(Int) -> Created) = object: Creatable
override fun create(i: Int): Created
return c(i)
这个函数接受一个函数并返回一个实际实现接口的对象。
【讨论】:
是的,我知道 typealias。正如 kotlinlang.org 所说:函数式接口与类型别名函数式接口和类型别名有不同的用途。类型别名只是现有类型的名称——它们不会创建新类型,而函数式接口会。类型别名只能有一个成员,而功能接口可以有多个非抽象成员和一个抽象成员。功能接口也可以实现和扩展其他接口。考虑到上述情况,函数式接口比类型别名更灵活并提供更多功能。 所以我想知道是否有在 lambda 上下文中使用接口的捷径(就好像它是 typealias)。以上是关于如何在kotlin中将lambdas与函数式接口一起使用并直接将lambda分配给var的主要内容,如果未能解决你的问题,请参考以下文章
Kotlin学习与实践 带接收者的lambda及Java的函数式接口