0

我一直在努力让 DSL 像这样工作。我想将 lambda 中的项目添加到人员内部的 mutableList 中。有人可以帮忙吗?

persons {
    Person("name")
    Person("name second")
}

执行 lambda 后的预期结果,所有这些项目将被放入 mutableList 中,如下所示:

mutableListOf(Person("name"), Person("name second"))
4

2 回答 2

2

与您所拥有的不完全一样,但应该能够使用类似的东西

data class Person(var name: String? = null)

class Persons : ArrayList<Person>() {
    fun person(block: Person.() -> Unit) {
        val person = Person().apply(block)
        add(person)
    }
}

fun persons(block : Persons.() -> Unit): Persons = Persons().apply(block)

fun main() {
    val personList = persons {
        person {
            name = "John"
        }
        person {
            name = "Jane"
        }
    }

    println(personList)
}

(这可以扩展为使用某种构建器模式以允许在数据类中使用不可变的 val)

于 2020-11-08T10:16:11.927 回答
2

假设这Person是一个:

data class Person(val name: String)

然后该行Person("name")什么都不做——它只是声明了一个未使用的实例。Person("name second")做同样的事情(一般来说,因为它是 lambda 中的最后一行,所以它作为 lambda expsession 的结果隐式返回,理论上,它可以稍后处理;无论如何,该 DSL 语法在一般情况下不起作用)。

您不仅需要声明实例,还需要将它们添加到列表中。因此,您需要声明一些辅助函数(person例如,接近所需的语法),它将在后台执行此操作:

class Persons {
    val delegate: MutableList<Person> = mutableListOf()

    fun person(name: String, block: Person.() -> Unit = {}) {
        delegate.add(Person(name).also(block))
    }
}

fun persons(block: Persons.() -> Unit) = Persons().also(block).delegate.toList() //mutation was needed only during construction, afterwards consider preserving immutability

用法:

val persons: List<Person> = persons {
    person("name")
    person("name second")
}
于 2020-11-08T10:59:25.480 回答