我正在为我的项目创建DSL,我真的希望能够使用来自多个接收器的字段/方法而不嵌套它们:

例如:

class Foo {
    val fooField = "Foo field"
}

class Bar {
    val barField = "Bar field"
}

fun main() {

    val foo = Foo()
    val bar = Bar()

    (foo..bar) {
        println(fooField)
        println(barField)
    }

}

代替:
class Foo {
    val fooField = "Foo field"

    operator fun invoke(block: Foo.() -> Unit) {
        block(this)
    }
}

class Bar {
    val barField = "Bar field"

    operator fun invoke(block: Bar.() -> Unit) {
        block(this)
    }
}

fun main() {

    val foo = Foo()
    val bar = Bar()

    foo {
        bar {
            println(fooField)
            println(barField)
        }
    }
}

我曾想过类似的事情:
class Buzz<T1, T2>(
    val t1: T1,
    val t2: T2
) {

    operator fun invoke(function: /* T1 + T2*/ () -> Unit) { // <--- ???
        function(/* t1 + t2*/)
    }
}

operator fun <T, R> T.rangeTo(r: R): Buzz<T, R> {
    return Buzz(this, r)
}

但是我可以在不使用样板的情况下以某种方式组合两个接收器吗?

最佳答案

您不能仅仅因为一个变量不能同时保存两个对象的引用就可以做到这一点。

但是类似的解决方案可能是使用一对,它可能使与您的问题相关联::

val foo = Foo()
val bar = Bar()

Pair(foo,bar).apply {         // this: Pair<Foo, Bar>
    println(first.fooField)
    println(second.barField)
}

注意*:这只是作为it does remove boilerplate by nested lambdas的建议,但另一方面却没有提供lambda with multiple receivers的解决方案

08-28 14:07