多类型对象表达式中的 Lambda

Lambda in multiple type object expression

我得到了一个 class Foo 可以做一些 work():

open class Foo() {      
    fun work(x: T) {
        // Effects taking place here  
    }
}

我还(但由其他人)提供了一种方法 useJob(),它使用具有单一方法 doJob().

的接口类型 Bar 的对象
fun useJob(bar: Bar)

interface Bar {
    fun doJob(x: T)
}

事实证明 Foo.work() 完成了 useJob() 期望的工作。但是,为了让 useJob() 调用 work(),我需要这样写:

useJob(object : Foo(), Bar { fun doJob(x: T) { work(x) } })

有没有办法使用 lambda 代替这个 blob?

编辑:@jrtapsell 评论让我意识到 Foo 实际上是开放的。

这是一个问题,useJob 需要一个接口而不是直接的函数类型。这样你只能做:

val bar = object : Bar {
    override fun doJob(x: String) = Foo().work(x)
}

useJob(bar)

实现此目的的最简单方法是使用创建 Bar 实例并接受函数调用的工厂方法:

fun job(func: (Param) -> Unit) : Bar = object: Bar { 
   override fun doJob(x: Param) = func(x)
}

那么你可以使用

useJob( job { Foo().work(it) } )

如果在Java中定义了Bar,你可以写成

useJob { Foo().work(x) }

val foo = Foo()
useJob { foo.work(x) }

避免每次都构造 Foo() 以防 useJob 多次调用其参数。

但是

note that this feature works only for Java interop; since Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported.

在不将 Bar 移动到 Java 的情况下,我会采用 joecks 的解决方案或定义 useJob 的重载(可能作为扩展方法)。哪个更好取决于您拥有多少种方法,例如 useJob 以及每种方法的用途。

你可以这样做:

// Mock class
class Param

// Provided code
open class Foo<T> {
    fun work(x: T) {
        // Effects taking place here
    }
}

fun useJob(bar: Bar) {}

interface Bar {
    fun doJob(x: Param)
}

// New code
object FooBar: Foo<Param>(), Bar {
    override fun doJob(x: Param) = work(x)
    fun use() = useJob(this)
}

fun x() {
    FooBar.use()
}

它需要更多 FooBar 对象的代码,但它会清理调用站点。