【问题标题】:Kotlin DSL variable imitationKotlin DSL 变量模仿
【发布时间】:2019-12-12 17:01:01
【问题描述】:

使用 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”中,并返回该值的句柄。

这个案例几乎是完美的,但它可以更清晰/更好吗?

【问题讨论】:

    标签: kotlin dsl kotlin-dsl


    【解决方案1】:

    您可以使用属性委托:

    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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-17
      • 1970-01-01
      • 2022-01-12
      • 2019-08-20
      • 2020-09-03
      • 2018-03-23
      • 1970-01-01
      • 2019-09-15
      相关资源
      最近更新 更多