跳到内容

属性

与参数类似,属性既可以通过构建器创建,也可以使用便捷的辅助方法创建

val android = PropertySpec.builder("android", String::class)
  .addModifiers(KModifier.PRIVATE)
  .build()

val helloWorld = TypeSpec.classBuilder("HelloWorld")
  .addProperty(android)
  .addProperty("robot", String::class, KModifier.PRIVATE)
  .build()

生成以下代码

class HelloWorld {
  private val android: String

  private val robot: String
}

当字段包含 KDoc、注解或字段初始化器时,需要使用扩展的 Builder 形式。字段初始化器使用与上述代码块相同的类似 String.format() 的语法

val android = PropertySpec.builder("android", String::class)
  .addModifiers(KModifier.PRIVATE)
  .initializer("%S + %L", "Oreo v.", 8.1)
  .build()

生成以下代码

private val android: String = "Oreo v." + 8.1

默认情况下,PropertySpec.Builder 会生成 val 属性。如果你需要 var,请使用 mutable()

val android = PropertySpec.builder("android", String::class)
  .mutable()
  .addModifiers(KModifier.PRIVATE)
  .initializer("%S + %L", "Oreo v.", 8.1)
  .build()

内联属性

KotlinPoet 建模内联属性的方式值得特别提及。以下代码片段

val android = PropertySpec.builder("android", String::class)
  .mutable()
  .addModifiers(KModifier.INLINE)
  .build()

将产生错误

java.lang.IllegalArgumentException: KotlinPoet doesn't allow setting the inline modifier on
properties. You should mark either the getter, the setter, or both inline.

确实,标记为 inline 的属性应至少包含一个访问器,该访问器将被编译器内联。让我们为该属性添加一个 getter

val android = PropertySpec.builder("android", String::class)
  .mutable()
  .getter(
    FunSpec.getterBuilder()
      .addModifiers(KModifier.INLINE)
      .addStatement("return %S", "foo")
      .build()
  )
  .build()

结果如下

var android: kotlin.String
  inline get() = "foo"

现在,如果我们想为上面的属性添加一个非内联的 setter 呢?我们可以这样做,而无需修改之前编写的任何代码

val android = PropertySpec.builder("android", String::class)
  .mutable()
  .getter(
    FunSpec.getterBuilder()
      .addModifiers(KModifier.INLINE)
      .addStatement("return %S", "foo")
      .build()
  )
  .setter(
    FunSpec.setterBuilder()
      .addParameter("value", String::class)
      .build()
  )
  .build()

我们得到了预期的结果

var android: kotlin.String
  inline get() = "foo"
  set(`value`) {
  }

最后,如果我们返回并为 setter 添加 KModifier.INLINE,KotlinPoet 可以很好地包装它并产生以下结果

inline var android: kotlin.String
  get() = "foo"
  set(`value`) {
  }

从 getter 或 setter 中移除修饰符将解开表达式。

另一方面,如果 KotlinPoet 允许直接将属性标记为 inline,那么每当访问器的状态发生变化时,程序员就必须手动添加/移除修饰符,以获得正确且可编译的输出。我们通过将访问器作为 inline 修饰符的真相源来解决这个问题。