为了开始使用Kotlin语言特性学习DSL的设计,下面我尝试使用一个玩具DSL来创建具有名称的成员组。我正在寻找下面的指针/提示
Groups.kt:31:45:错误:未解决的引用:成员val =组{成员{名称(“鲍勃”)}成员{名称(“桑迪”)}}
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)
}当前,上述代码的输出是
成员(鲍勃)、成员(桑迪)
发布于 2018-10-20 14:02:27
我怎样才能避免用分号分隔组?
通过使用惯用格式,使用单独的行。毕竟,DSL的全部目的是通过显示层次结构来使代码非常可读性,并且在一行上做任何事情都会违背wole的目的:
val grp = group {
member {
name ("Bob")
}
member {
name ("Sandy")
}
}我可以使用lambda来设置名称而不是函数调用吗?
删除name函数并简单地为属性赋值更符合逻辑和惯用:
name = "Bob"但是是的,您也可以将name函数替换为
fun name(block: () -> String) {
this.name = block()
}并使用
name {
"Sandy"
}我是否可以避免在类成员中名称是可变的?
是的:传递给成员()函数的lambda将自定义一个额外的MemberBuilder类,这个类是可变的,但是允许创建一个不可变的成员:
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。
https://stackoverflow.com/questions/52906363
复制相似问题