函数¶
以上所有函数都有代码体。使用 KModifier.ABSTRACT
可以得到一个没有代码体的函数。这仅在函数包含在抽象类或接口中时才合法。
val flux = FunSpec.builder("flux")
.addModifiers(KModifier.ABSTRACT, KModifier.PROTECTED)
.build()
val helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(KModifier.ABSTRACT)
.addFunction(flux)
.build()
这会生成如下代码
abstract class HelloWorld {
protected abstract fun flux()
}
其他修饰符在允许的情况下都有效。
方法(Functions)还包含参数、可变参数 (varargs)、KDoc、注解、类型变量、返回类型以及扩展函数的接收者类型。所有这些都通过 FunSpec.Builder
进行配置。
扩展函数¶
通过指定 receiver
可以生成扩展函数。
val square = FunSpec.builder("square")
.receiver(Int::class)
.returns(Int::class)
.addStatement("var s = this * this")
.addStatement("return s")
.build()
输出如下
fun Int.square(): Int {
val s = this * this
return s
}
单表达式函数¶
KotlinPoet 可以识别单表达式函数并正确打印。它将每个代码体以 return
开头的函数视为单表达式函数。
val abs = FunSpec.builder("abs")
.addParameter("x", Int::class)
.returns(Int::class)
.addStatement("return if (x < 0) -x else x")
.build()
输出如下
fun abs(x: Int): Int = if (x < 0) -x else x
默认函数参数¶
考虑下面的例子。函数参数 b
的默认值为 0,以避免函数重载。
fun add(a: Int, b: Int = 0) {
print("a + b = ${a + b}")
}
使用 defaultValue()
构建器函数声明函数参数的默认值。
FunSpec.builder("add")
.addParameter("a", Int::class)
.addParameter(
ParameterSpec.builder("b", Int::class)
.defaultValue("%L", 0)
.build()
)
.addStatement("print(\"a + b = ${a + b}\")")
.build()
换行是明确的¶
为了保证代码的正确性,从 2.0 版本开始,即使代码行超出长度限制,KotlinPoet 也不会将代码块中的空格替换为换行符。例如,我们来看这个函数
val funSpec = FunSpec.builder("foo")
.addStatement("return (100..10000).map { number -> number * number }.map { number -> number.toString() }.also { string -> println(string) }")
.build()
该函数将始终像这样打印出来
public fun foo() = (100..10000).map { number -> number * number }.map { number -> number.toString() }.also { string -> println(string) }
虽然输出是正确的,但生成的代码行相当长且难以阅读。KotlinPoet 无法理解表达式的上下文并为你调整格式,但你可以使用一个技巧来声明一个断行空间——在你确定可以安全地选择换行的地方使用 ♢
符号。让我们将此应用于我们的示例
val funSpec = FunSpec.builder("foo")
.addStatement("return (100..10000).map { number ->♢number * number♢}.map { number ->♢number.toString()♢}.also { string ->♢println(string)♢}")
.build()
现在这将产生以下结果
public fun foo(): Unit = (100..10000).map { number -> number * number }.map { number ->
number.toString() }.also { string -> println(string) }
这稍微好一些,但远非完美——你可以随意尝试其他格式修饰符,例如 KotlinPoet 支持的标准 \n
字符,或者库自带的缩进格式修饰符(⇥
和 ⇤
)(有关更多信息,请参阅 CodeBlock
的文档)。
最后,不完美的格式是该库的一个已知限制,因为 KotlinPoet 在设计上优先考虑生成代码的正确性而非风格。如果正确且整洁的格式对你的使用场景很重要,请考虑使用专用的代码格式化工具对 KotlinPoet 的输出进行后处理。