Kotlin DSL - 带有多个接收器的通用lambda。

问题描述 投票:0回答:1

我正在为我的项目创建一个DSL,我真的希望能够使用来自多个接收器的fieldmethods而不需要嵌套它们。

例如:

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)
}

但我能不能以某种方式结合两个接收器而不使用模板?

kotlin dsl
1个回答
0
投票

你不能这样做,因为一个变量不能同时容纳两个对象的引用。

但类似的解决方案可以是使用一对变量,它可以是 关联* 与你的问题。

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

© www.soinside.com 2019 - 2024. All rights reserved.