如何在Kotlin中将功能接口实现为lambda?

我想将功能性kotlin接口(具有单个抽象方法的接口)实现为kotlin lambda。该怎么做?

Kotlin界面

@FunctionalInterface
interface Foo{
  fun bar(input: String): String 
}

Kotlin实施

fun createFoo(): Foo {
   return { input: String -> "Hello $input!" }
}

↑不编译↑

它必须作为对象来实现,这很难看。

fun createFoo() = 
     object : Foo{
            override fun bar(input: String)= "Hello $input"
     }

编辑:从Java到kotlin纠正了我的示例界面

tmc19850121 回答:如何在Kotlin中将功能接口实现为lambda?

  

我想将功能性kotlin接口(具有单个抽象方法的接口)实现为kotlin lambda。该怎么做?

不能

  

它必须作为对象来实现,这很难看。

确实。


您有两个选择:

1。)使用typealias

typealias Foo = (String) -> String

fun createFoo(): Foo = { "Hello $it!" }

2。),具体取决于您的API,您可以定义一个扩展函数,该扩展函数以(String) -> String参数的形式接收功能类型crossinline,然后在object: __块内调用它。这样,您可以将object:隐藏在给定的函数中,并且在外部仍然可以使用lambda参数来调用它。不过,在这种情况下似乎并不适用。

,

我认为没有语言级别的选项可以执行此操作,但是您可以将“丑陋的”代码抽象为一个辅助方法,以便在实际需要业务逻辑的地方更容易阅读:

帮助方法

fun Foo(body: (String) -> String) = object : Foo{
  override fun bar(input: String)= body(input)
}

公司代码

fun createFoo():Foo {
  return Foo {input:String -> "Hello $input!"}
}
,

在您的情况下,使用Java接口会更容易:

fun createFoo() : Foo = Foo { "hello $it" }

但是,因为有了Kotlin界面,您在这里有点不走运。这是与此相关的问题:KT-7770

对此的一种解决方法是(但主要取决于您如何使用该接口)具有如下所示的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"
  }
}

对应的FooFactory-接口可能如下所示:

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
     }

或者,也可以让Foo感觉像Kotlin一样:

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代码与上面的相同,其中JFooFoo指向另一个软件包;从Java中看不到typealias。 Kotlin方面将更改为以下内容:

class KFactory : FooFactory {
  override fun createFoo() : Foo = {
    "hello $it"
  }
}

Factory-接口也可以替换:

interface FooFactory {
  fun createFoo() : Foo
}

在引擎盖下,所有东西保持不变。我们在Kotlin中使用过(String) -> String,在Java中使用过Foo-functional-interface。

,

只需将 fun 关键字添加到您的接口声明中:

fun interface Foo {
    fun bar(input: String): String 
}

它是 Kotlin 中函数式接口的表示法(而不是 Java 中的 @FunctionalInterface 注释)。

现在你可以像这样实现它:

Foo { input: String -> "Hello $input!" }
,

要在任何需要的地方使用Kotlin lambda到Java SAM接口的转换,只需在lambda之前指定接口的名称即可。

fun createFoo(): Foo {
   return Foo { input:String -> "Hello $input!" }
}

它甚至不需要那么长。

fun createFoo(): Foo {
   return Foo { "Hello $it!" }
}

只要接口只有一个方法并且用Java声明,这就是您要做的所有事情。

,

如果伴随对象实现invoke函数并使用lambda,则该函数有效。

Kotlin界面

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 lambda,请参见KT-7770

在Kotlin中,将功能/ SAM接口视为反模式,应声明功能类型:(String)->String。函数类型可以表示为类型别名,以使其外观和感觉像一个接口:typealias Foo=(String)->String。 注意:仅在Kotlin中,typealias在Java代码中不可见!

本文链接:https://www.f2er.com/3158760.html

大家都在问