如何在Kotlin中实现lambda功能接口?
我想实现一个功能性的kotlin接口(带有一个抽象方法的接口)作为kotlin lambda。怎么做 Kotlin接口如何在Kotlin中实现lambda功能接口?,kotlin,lambda,functional-interface,Kotlin,Lambda,Functional Interface,我想实现一个功能性的kotlin接口(带有一个抽象方法的接口)作为kotlin lambda。怎么做 Kotlin接口 @FunctionalInterface interface Foo{ fun bar(input: String): String } fun createFoo():Foo { return Foo {input:String -> "Hello $input!"} } interface Foo{ fun bar(input: String): S
@FunctionalInterface
interface Foo{
fun bar(input: String): String
}
fun createFoo():Foo {
return Foo {input:String -> "Hello $input!"}
}
interface Foo{
fun bar(input: String): String
companion object {
inline operator fun invoke(crossinline function: (String) -> String) =
object : Foo{
override fun bar(input: String) = function(input)
}
}
}
Kotlin实施
fun createFoo(): Foo {
return { input: String -> "Hello $input!" }
}
↑ 不编译↑
它必须作为对象来实现,这非常难看
fun createFoo() =
object : Foo{
override fun bar(input: String)= "Hello $input"
}
编辑:更正了我从java到kotlin的示例接口我认为没有语言级别的选项可以做到这一点,但您可以将“丑陋”的代码抽象到帮助器方法中,以便在实际需要业务逻辑的地方更容易阅读: 助手方法
fun Foo(body: (String) -> String) = object : Foo{
override fun bar(input: String)= body(input)
}
业务代码
@FunctionalInterface
interface Foo{
fun bar(input: String): String
}
fun createFoo():Foo {
return Foo {input:String -> "Hello $input!"}
}
interface Foo{
fun bar(input: String): String
companion object {
inline operator fun invoke(crossinline function: (String) -> String) =
object : Foo{
override fun bar(input: String) = function(input)
}
}
}
要在任意位置使用Kotlin lambda到Java SAM接口转换,只需在lambda之前指定接口的名称
fun createFoo(): Foo {
return Foo { input:String -> "Hello $input!" }
}
它甚至不需要那么长
fun createFoo(): Foo {
return Foo { "Hello $it!" }
}
只要接口只有一个方法,并且是用Java声明的,您就只需要这样做。在您的情况下,用Java声明接口会更容易:
fun createFoo() : Foo = Foo { "hello $it" }
但由于您使用的是Kotlin接口,因此您在这里有点运气不佳。以下是与此相关的一个问题: 解决这个问题的一个办法是(但这主要取决于您如何使用该接口),将Kotlin接口作为Java端的主要入口点,如下所示:
interface Foo : (String) -> String
在Kotlin端,您不会使用它,而Java端应该只使用它来交付函数,例如
// Java class
public class JFooFactory implements FooFactory {
@Override
@NotNull
public Foo createFoo() { // uses the Foo-interface from Kotlin
return input -> "hello " + input;
}
}
// Kotlin equivalent:
class KFactory : FooFactory {
override fun createFoo() : (String) -> String = {
"hello $it"
}
}
其中对应的foodfactory
-接口可能如下所示:
interface FooFactory {
fun createFoo() : (String) -> String
}
listOf(KFooFactory(), JFooFactory())
.map {
it.createFoo()
}
.forEach { func : (String) -> String -> // i.e. func is of (sub)type (String) -> String
func("demo") // calling it to deliver "hello demo" twice
}
用法可能如下所示:
interface FooFactory {
fun createFoo() : (String) -> String
}
listOf(KFooFactory(), JFooFactory())
.map {
it.createFoo()
}
.forEach { func : (String) -> String -> // i.e. func is of (sub)type (String) -> String
func("demo") // calling it to deliver "hello demo" twice
}
或者,为了让Kotlin也有那种Foo
-的感觉,你可以按如下方式来做:
typealias Foo = (String) -> String
interface JFoo : Foo
// or if you put the interface in its own package you could also use:
interface Foo : someother.package.Foo
然后Java代码保持与上面相同,要么使用JFoo
,要么使用Foo
指向另一个包;typealias在Java中不可见。Kotlin侧将更改为以下内容:
class KFactory : FooFactory {
override fun createFoo() : Foo = {
"hello $it"
}
}
工厂
-接口也可以更换:
interface FooFactory {
fun createFoo() : Foo
}
但在引擎盖下,一切都保持不变。我们在Kotlin中使用了(String)->String
,在Java中使用了Foo
-功能接口
我想实现一个功能性的kotlin接口(带有一个抽象方法的接口)作为kotlin lambda。怎么做
不能
它必须作为对象来实现,这非常难看
fun createFoo() =
object : Foo{
override fun bar(input: String)= "Hello $input"
}
的确如此
您有两个选择: 1.)使用
typealias
typealias Foo = (String) -> String
fun createFoo(): Foo = { "Hello $it!" }
2.)根据您的API,您可以定义一个扩展函数,该函数将函数类型(String)->String
作为交叉内联
参数接收,然后在对象内调用它:\uuuu
块。这样,您就可以在给定函数中隐藏对象:
,并且在外部仍然可以使用lambda参数调用它。但在这种情况下似乎不适用。因为Kotlin v1.4
版本1.4将支持SAM转换,并使用新的类型推断算法
见:
Kotlin v1.4之前 如果伴生对象使用lambda实现
invoke
函数,则该函数有效
Kotlin接口
@FunctionalInterface
interface Foo{
fun bar(input: String): String
}
fun createFoo():Foo {
return Foo {input:String -> "Hello $input!"}
}
interface Foo{
fun bar(input: String): String
companion object {
inline operator fun invoke(crossinline function: (String) -> String) =
object : Foo{
override fun bar(input: String) = function(input)
}
}
}
Kotlin实施
fun createFoo()= Foo { input: String -> "Hello $input!" }
kotlin中定义的功能/SAM接口在设计上不能实现为kotlin lambdas,请参阅 在Kotlin中,函数/SAM接口被视为反模式,应该声明函数类型:
(String)->String
。函数类型可以表示为typealias,使其看起来和感觉像一个接口:typealias Foo=(String)->String
注意:typealias在Java代码中不可见,仅在Kotlin中可见 只需在界面声明中添加
fun
关键字即可:
fun interface Foo {
fun bar(input: String): String
}
它是Kotlin中函数接口的表示法(而不是Java中的@functioninterface
注释)
现在您可以这样实现它:
Foo { input: String -> "Hello $input!" }
我更新了我的问题,接口是在kotlin中定义的,而不是在java中定义的。@Chriss,此解决方案适用于在kotlin中定义的接口。但是,您可以通过向
Foo
函数添加inline
修饰符使它变得更好:inline fun Foo(crossinline body:(String)->String)=object:Foo{…}
。它将阻止在创建Foo
期间创建额外的(String)->String
实例。另外,当您使用此函数时,不必显式指定参数的类型,以下操作将起作用:Foo{input->“Hello$input!”}
以及Foo{“Hello$it!”}
。我更新了我的问题,接口是在kotlin中定义的,而不是java。不允许对kotlin接口进行SAM转换。引用文档:“请注意,此功能[SAM转换]仅适用于Java互操作;由于Kotlin具有适当的函数类型,因此不需要将函数自动转换为Kotlin接口的实现,因此不受支持。”以下是与此相关的问题: