首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >改进DSL语法

改进DSL语法
EN

Stack Overflow用户
提问于 2018-10-20 13:48:14
回答 1查看 59关注 0票数 0

为了开始使用Kotlin语言特性学习DSL的设计,下面我尝试使用一个玩具DSL来创建具有名称的成员组。我正在寻找下面的指针/提示

  1. 如果编译器没有分号,那么如何避免使用分号分隔组?

Groups.kt:31:45:错误:未解决的引用:成员val =组{成员{名称(“鲍勃”)}成员{名称(“桑迪”)}}

  1. 我可以使用lambda来设置name而不是函数调用吗?
  2. 我能避免nameMEMBER类中是可变的吗?

我的代码是

代码语言:javascript
复制
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)
}

当前,上述代码的输出是

成员(鲍勃)、成员(桑迪)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-20 14:02:27

我怎样才能避免用分号分隔组?

通过使用惯用格式,使用单独的行。毕竟,DSL的全部目的是通过显示层次结构来使代码非常可读性,并且在一行上做任何事情都会违背wole的目的:

代码语言:javascript
复制
val grp = group { 
    member { 
        name ("Bob") 
    }
    member { 
        name ("Sandy") 
    } 
}

我可以使用lambda来设置名称而不是函数调用吗?

删除name函数并简单地为属性赋值更符合逻辑和惯用:

代码语言:javascript
复制
name = "Bob"

但是是的,您也可以将name函数替换为

代码语言:javascript
复制
fun name(block: () -> String) {
    this.name = block()
}

并使用

代码语言:javascript
复制
name {
    "Sandy"
}

我是否可以避免在类成员中名称是可变的?

是的:传递给成员()函数的lambda将自定义一个额外的MemberBuilder类,这个类是可变的,但是允许创建一个不可变的成员:

代码语言:javascript
复制
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。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52906363

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档