【问题标题】:How should I define these complex initializer for a property我应该如何为属性定义这些复杂的初始化程序
【发布时间】:2018-05-01 10:45:43
【问题描述】:

虽然我检查了 kotlinpoet 代码中的所有测试,但我没有找到合适的方法来实现以下目标代码,或者我不确定我是否使用了最好的方法来做到这一点。如果有人能提供一些关于此的 cmets,那将不胜感激。

这些属性是在类的函数中定义的

目标代码 1

val outputState = StateType1(iouValue, ourIdentity, otherParty)

我使用下面的代码来生成上面的代码

.addCode(CodeBlock.of("%L",
    PropertySpec.builder("outputState", ClassName("","StateType1"))
        .initializer(CodeBlock.of("%T(%L, %L, %L)", ClassName("","StateType1"), "iouValue", "ourIdentity", "otherParty"))
        .build()))

但问题是这个 outputState 可能来自不同的类型,例如 StateType1 有 3 个参数,但 StateTyp2 可能只有 1 个参数,我应该如何动态定义我的 kotlinpoet 代码以生成正确的目标代码。

目标代码 2

val txBuilder = TransactionBuilder(notary = notary)
    .addOutputState(outputState, TEMPLATE_CONTRACT_ID)

我没有找到具有这种情况的参考测试用例,在属性的初始化程序之后直接调用它的函数。

【问题讨论】:

    标签: kotlin kotlinpoet


    【解决方案1】:

    第一个例子使用CodeBlock.Builder,它给你更多的灵活性来构造CodeBlocks:

    fun createConstructorCall(type: TypeName, vararg args: String): CodeBlock {
      val argsCode = args
          .map { CodeBlock.of("%L", it) }
          .joinToCode(separator = ", ", prefix = "(", suffix = ")")
      return CodeBlock.Builder()
          .add("%T", type)
          .add(argsCode)
          .build()
    }
    
    val className = ClassName("", "StateType1")
    val codeBlock = CodeBlock.of("%L", PropertySpec.builder("outputState", className)
        .initializer(createConstructorCall(className, "iouValue", "ourIdentity", "otherParty"))
        .build())
    assertThat(codeBlock.toString()).isEqualTo("""
      |val outputState: StateType1 = StateType1(iouValue, ourIdentity, otherParty)
      |""".trimMargin())
    

    在第二个示例中,我们并没有真正提供任何特别的东西,将您的代码作为字符串传递,并在需要时随意使用占位符进行参数化:

    val className1 = ClassName("", "TransactionBuilder")
    val codeBlock1 = CodeBlock.of("%L", PropertySpec.builder("txBuilder", className)
        .initializer(
            "%T(notary = notary)\n.addOutputState(outputState, TEMPLATE_CONTRACT_ID)",
            className1)
        .build())
    assertThat(codeBlock1.toString()).isEqualTo("""
      |val txBuilder: StateType1 = TransactionBuilder(notary = notary)
      |        .addOutputState(outputState, TEMPLATE_CONTRACT_ID)
      |""".trimMargin())
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-10
      • 2014-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多