Kotlin DSL变量模仿

时间:2019-12-12 17:01:01

标签: kotlin dsl kotlin-dsl

使用Kotlin类型安全的构建器可能最终会编写此代码

code {
  dict["a"] = "foo"; // dict is a Map hidden inside that can associate some name to some value
  println(dict["a"]); // usage of this value
}

此代码还可以,但是有一个问题:“ a”只是一个字符串。我希望它像一个用户定义的变量-编译器可以识别的标识符,启用自动完成功能。

有没有办法将其变成这样?

code {
  a = "foo"; // now 'a' is not a Map key, but an identifier recognized by Kotlin as a variable name
  println(a);
}

如果我将code的lambda设为某个对象的扩展函数,并且内部定义了字段a,则可以这样做。这不是我想要的。我也希望能够使用其他变量(具有未知名称)。

可能的解决方法是

code {
  var a = v("a", "foo");
  println(a);
}

v是扩展对象的方法,在其中将值“ foo”存储在“ dict”中,并返回该值的句柄。

这种情况几乎是完美的,但是可以通过某种方式更清楚/更好吗?

1 个答案:

答案 0 :(得分:2)

您可以使用属性委派:

class Code {
    private val dict = mutableMapOf<String, String>()

    operator fun String.provideDelegate(
        thisRef: Any?,
        prop: KProperty<*>
    ): MutableMap<String, String> {
        dict[prop.name] = this
        return dict
    }
}

用例:

code {
    var a by "foo" // dict = {a=foo}
    println(a) // foo
    a = "bar" // dict = {a=bar}
    println(a) // bar
}