带可选字段的Kotlin DSL

问题描述 投票:0回答:1

我目前正在学习Kotlin DSL。

我已经玩了一段时间了,但是我无法解决我的用例。我有一个简单的DSL,我不太在意它的类型,只要能实现这样的语法即可。

    private fun getObj(): SET {
        return SET {
            ITEM {
                A = null
                B = "Hello world"
                C
                // D - exists in DSL but omitted here
            }
        }
    }

在后台,我现在想区分某些值在 ITEM 块。B 是很容易的,它只是价值,但它变得很难为 AC. 不知怎的,我无法分辨出... nullno value 集。目前我的构建器是这样的,但我愿意改变它来实现上面的语法。

class ITEMBuilder {
    var A: String? = null
    var B: String? = null
    var C: String? = null
    var D: String? = null

    fun build() = ITEM(
        ItemValue(A),
        ItemValue(B),
        ItemValue(C),
        ItemValue(D)
    )
}

class ItemValue(val include: Boolean? = false, val value: String? = null) {
    constructor(value: String? = null): this(null != value, value)
}

当我有了最终的对象,我希望能够告诉4个不同的阶段 在ITEM下的每个字段。

  • 值设置
  • 空套
  • 无值
  • 遗漏

我尝试了不同的类型,但没有成功,因为大多数东西都会影响语法。我还试着改变构建器中的gettersetters,也许可以在那里捕捉更新,并有一个额外的内部属性被更新--但这两个属性都不存在。getset 被调用为nullno值。我也试着把字段改成函数,但我有丑陋的括号。() 在DSL语法中。

如果有人能帮我解决这个问题就太好了。

先谢谢你

kotlin dsl kotlin-dsl
1个回答
1
投票

你可以用接收机来实现。这里有一个单一参数的例子(本例中的字段)。

//Use like this
val item = ITEM {
        A = "Yay"
        B //Not omitted, but also not set
        //C can be omitted
        D = null
    }

这相当于

Item(//Included and set to "Yay"
     a=ItemValue(include=true, hasBeenSet=true, value="Yay"), 
     //Included, but not yet set
     b=ItemValue(include=true, hasBeenSet=false, value=null), 
     //Not included, and so not yet set
     c=ItemValue(include=false, hasBeenSet=false, value=null), 
     //Included, and set to null (Same as A)
     d=ItemValue(include=true, hasBeenSet=true, value=null))

你可以借助于类型为 String? 并覆盖它们的设置器来修改类型为 ItemValue. 我包括一个 hasBeenSet 财产 ItemValue 来显示它是否已被设置。

要在不设置属性的情况下将其标记为包含的属性,您可以覆盖获取器,使其修改实际字段,使其成为 ItemValue(true, false),这意味着它们被包含但没有被设置。

class Builder {
    var A: String? = null
        set(value) {
            a = ItemValue(true, true, value)
        }
        get() {
            a = ItemValue(true, false)
            return field
        }
    var B: String? = null
        set(value) {
            b = ItemValue(true, true, value)
        }
        get() {
            b = ItemValue(true, false)
            return field
        }
    var C: String? = null
        set(value) {
            c = ItemValue(true, true, value)
        }
        get() {
            c = ItemValue(true, false)
            return field
        }
    var D: String? = null
        set(value) {
            d = ItemValue(true, true, value)
        }
        get() {
            d = ItemValue(true, false)
            return field
        }

    var a: ItemValue = ItemValue(false, false)
    var b: ItemValue = ItemValue(false, false)
    var c: ItemValue = ItemValue(false, false)
    var d: ItemValue = ItemValue(false, false)

    fun build(): Item {
        return Item(a, b, c, d)
    }
}

fun ITEM(setters: Builder.() -> Unit): Item {
    val builder = Builder()
    builder.setters()
    return builder.build()
}

data class Item(val a: ItemValue, val b: ItemValue, val c: ItemValue, val d: ItemValue)
data class ItemValue(val include: Boolean, val hasBeenSet: Boolean, val value: String? = null)

这里是Kotlin Playground的链接。. 你可以运行它,自己看看输出。

© www.soinside.com 2019 - 2024. All rights reserved.