Kotlin DSL 自动 add/generate 到 MutableList

Kotlin DSL automatically add/generate to MutableList

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

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

lambda 执行后的预期结果,所有这些项目将像这样放在 mutableList 中:

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

与您使用的不完全一样,但应该可以使用类似

的东西
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)
}

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

假设 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")
}