如何使场科特林DSL建设者需要

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

在科特林,创建自定义DSL的时候,是什么迫使填充生成器的扩展函数内所需的字段在编译时的最佳方式。例如。:

person {
    name = "John Doe" // this field needs to be set always, or compile error
    age = 25
}

迫使它的方法之一是在一个函数的参数,而不是扩展功能的机构设置值。

person(name = "John Doe") {
    age = 25
}

但是,它使一个有点不可读,如果有多个必填字段。

有没有其他办法?

kotlin
1个回答
0
投票

简单,抛出一个异常,如果它不是在你的DLS定义的块之后

fun person(block: (Person) -> Unit): Person {
val p = Person()
block(p)
if (p.name == null) {
  // throw some exception
}
return p
}

或者,如果你想在编译的时候去执行,只是让一些无用的返回外块如果没有定义,像空。

fun person(block: (Person) -> Unit): Person? {
val p = Person()
block(p)
if (p.name == null) {
  return null
}
return p
}

我猜你会关闭this example所以也许解决将是更好的例子情况:

fun Person.address(block: Address.() -> Unit) {
// city is required
var tempAddress = Address().apply(block)
if (tempAddress.city == null) {
   // throw here
}
}

但被定义,如果我们要确保一切,但同时也让你在任何顺序做到这一点,在编译时破裂。简单,有两种类型!

data class Person(var name: String = null,
              var age: Int = null,
              var address: Address = null)
data class PersonBuilder(var name: String? = null,
              var age: Int? = null,
              var address: Address? = null)
fun person(block: (PersonBuilder) -> Unit): Person {
    val pb = PersonBuilder()
    block(p)
    val p = Person(pb.name, pb.age, pb.address)
    return p
}

这样,你得到你非严格型打造,但它最好是空少的结束。这是一个有趣的问题,谢谢。

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