%M 用于成员¶
与类型类似,KotlinPoet 为成员(函数和属性)提供了一个特殊的占位符,这在你的代码需要访问顶层成员和对象内部声明的成员时非常方便。使用 %M
来引用成员,将 MemberName
的实例作为占位符的参数传入,KotlinPoet 将自动处理导入
val createTaco = MemberName("com.squareup.tacos", "createTaco")
val isVegan = MemberName("com.squareup.tacos", "isVegan")
val file = FileSpec.builder("com.squareup.example", "TacoTest")
.addFunction(
FunSpec.builder("main")
.addStatement("val taco = %M()", createTaco)
.addStatement("println(taco.%M)", isVegan)
.build()
)
.build()
println(file)
上面的代码生成以下文件
package com.squareup.example
import com.squareup.tacos.createTaco
import com.squareup.tacos.isVegan
fun main() {
val taco = createTaco()
println(taco.isVegan)
}
如你所见,也可以使用 %M
来引用扩展函数和属性。你只需要确保成员可以导入而不会发生简单名称冲突,否则导入将失败,并且代码生成器的输出将无法通过编译。不过,有一种方法可以解决这种情况 - 使用 FileSpec.addAliasedImport()
为冲突的 MemberName
创建别名
val createTaco = MemberName("com.squareup.tacos", "createTaco")
val createCake = MemberName("com.squareup.cakes", "createCake")
val isTacoVegan = MemberName("com.squareup.tacos", "isVegan")
val isCakeVegan = MemberName("com.squareup.cakes", "isVegan")
val file = FileSpec.builder("com.squareup.example", "Test")
.addAliasedImport(isTacoVegan, "isTacoVegan")
.addAliasedImport(isCakeVegan, "isCakeVegan")
.addFunction(
FunSpec.builder("main")
.addStatement("val taco = %M()", createTaco)
.addStatement("val cake = %M()", createCake)
.addStatement("println(taco.%M)", isTacoVegan)
.addStatement("println(cake.%M)", isCakeVegan)
.build()
)
.build()
println(file)
KotlinPoet 将为 com.squareup.tacos2.isVegan
生成一个别名导入
package com.squareup.example
import com.squareup.cakes.createCake
import com.squareup.tacos.createTaco
import com.squareup.cakes.isVegan as isCakeVegan
import com.squareup.tacos.isVegan as isTacoVegan
fun main() {
val taco = createTaco()
val cake = createCake()
println(taco.isTacoVegan)
println(cake.isCakeVegan)
}
MemberName 和操作符¶
MemberName 也支持操作符,你可以使用 MemberName(String, KOperator)
或 MemberName(ClassName, KOperator)
来导入和引用操作符。
val taco = ClassName("com.squareup.tacos", "Taco")
val meat = ClassName("com.squareup.tacos.ingredient", "Meat")
val iterator = MemberName("com.squareup.tacos.internal", KOperator.ITERATOR)
val minusAssign = MemberName("com.squareup.tacos.internal", KOperator.MINUS_ASSIGN)
val file = FileSpec.builder("com.example", "Test")
.addFunction(
FunSpec.builder("makeTacoHealthy")
.addParameter("taco", taco)
.beginControlFlow("for (ingredient %M taco)", iterator)
.addStatement("if (ingredient is %T) taco %M ingredient", meat, minusAssign)
.endControlFlow()
.addStatement("return taco")
.build()
)
.build()
println(file)
KotlinPoet 将导入扩展操作符函数并输出操作符。
package com.example
import com.squareup.tacos.Taco
import com.squareup.tacos.ingredient.Meat
import com.squareup.tacos.internal.iterator
import com.squareup.tacos.internal.minusAssign
fun makeTacoHealthy(taco: Taco) {
for (ingredient in taco) {
if (ingredient is Meat) taco -= ingredient
}
return taco
}