要开始学习使用Kotlin语言功能的DSL设计,我有 下面尝试在玩具DSL上创建具有成员的成员组 有名字。我正在寻找以下内容的指针/提示
Groups.kt:31:45:错误:未解决的引用:成员 val grp =组{成员{名称(“鲍勃”)}成员{名称(“桑迪”)}}
我可以使用lambda来设置name
而不是函数调用吗?
我可以避免在类name
中使MEMBER
变得可变吗?
我的代码是
fun group(create: GROUP.() -> Unit) = GROUP().apply(create)
class GROUP {
private val members = mutableSetOf<MEMBER>()
fun member(create: MEMBER.() -> Unit) {
val member = MEMBER()
member.create()
members.add(member)
}
override fun toString() = members.toString()
}
class MEMBER() {
var name = ""
set(value) {
field = value
}
fun name(nameToSet: String) {
name = nameToSet
}
override fun toString() = "MEMBER(" + name + ")"
}
fun main(args: Array<String>) {
val grp = group { member { name ("Bob") }; member { name ("Sandy") } }
println(grp)
}
当前上述代码的输出为
[鲍勃(成员),桑迪(成员)]
答案 0 :(得分:1)
如何避免用分号分隔组
使用惯用格式,使用单独的行。毕竟,DSL的全部目的是通过显示层次结构来使代码非常易读,而在一行上完成所有操作都将达到令人讨厌的目的:
val grp = group {
member {
name ("Bob")
}
member {
name ("Sandy")
}
}
我可以使用lambda来设置名称而不是函数调用吗?
删除名称函数并简单地为属性分配一个值会更合乎逻辑和习惯:
name = "Bob"
但是,您也可以用
替换您的姓名功能fun name(block: () -> String) {
this.name = block()
}
并使用
name {
"Sandy"
}
我可以避免在MEMBER类中使名称可变吗?
是的:传递给member()函数的lambda将自定义一个额外的MemberBuilder类,该类是可变的,但允许创建一个不变的MEMBER:
fun group(create: GROUP.() -> Unit) = GROUP().apply(create)
class GROUP {
private val members = mutableSetOf<MEMBER>()
fun member(configure: MemberBuilder.() -> Unit) {
val memberBuilder = MemberBuilder()
memberBuilder.configure()
members.add(memberBuilder.build())
}
override fun toString() = members.toString()
}
class MEMBER(val name: String) {
override fun toString() = "MEMBER($name)"
}
class MemberBuilder {
var name = "";
fun build() = MEMBER(name)
}
fun main(args: Array<String>) {
val grp = group {
member {
name = "Bob"
}
member {
name = "Sandy"
}
}
println(grp)
}
此外,请注意,按照惯例,类是PascalCased,而不是ALL_CAPS。