kotlin 1.2.71
我正在编写以下DSL,并希望使其尽可能接近此样本:
android {
compileSdkVersion 26
buildToolsVersion "28.0.3"
}
我正在使用中缀函数,lambda和接收器来执行此操作。在DSL内,我必须使用it
关键字,否则无法使用infix函数。只是想知道是否有办法做到这一点?
另一个问题:在我的infix函数中,是否需要将其用作扩展函数并在其键盘前面加上Android键盘,即infix fun Android.buildToolsVersion(...)
fun main(args: Array<String>) {
val androidConfig = android {
it buildToolsVersion "28.0.3"
it compileSdkVersion 26
}
println(androidConfig.toConsolePrint)
}
private fun android(block: Android.(Android) -> Unit): Android {
val android = Android()
android.block(android)
return android
}
class Android(var compileSdkVersion: Int = 0,
var buildToolsVersion: String = "") {
infix fun Android.buildToolsVersion(buildToolsVersion: String) {
this.buildToolsVersion = buildToolsVersion
}
infix fun Android.compileSdkVersion(sdkVersion: Int) {
compileSdkVersion = sdkVersion
}
}
private val Android.toConsolePrint: String
get() {
return "compileSDK: $compileSdkVersion build tools: $buildToolsVersion"
}
答案 0 :(得分:4)
要澄清一下:it
不需要infix
才能工作。您也可以只写this
,例如this compileSdkVersion 26
。
还请注意,只需具备以下条件即可:
fun android(block: Android.() -> Unit) = Android().apply(block)
class Android(var compileSdkVersion: Int = 0,
var buildToolsVersion: String = "")
然后,用法仅与您显示的=
不同:
val androidConfig = android {
buildToolsVersion = "28.0.3"
compileSdkVersion = 26
}
但是好处是更大的:要维护的代码要少得多;-)
关于您提到的另一点,您需要提供扩展功能。您不需要。只需将infix fun Android.buildToolsVersion
放在class Android
内而不用Android.
就可以了,例如:
class Android(var compileSdkVersion: Int = 0,
var buildToolsVersion: String = "") {
infix fun buildToolsVersion(buildToolsVersion: String) {
this.buildToolsVersion = buildToolsVersion
}
现在关于consolePrint
。在我看来,这也相当复杂。那么在class Android
中,下面的内容呢?
fun toConsolePrint() = "compileSDK: $compileSdkVersion build tools: $buildToolsVersion"
这实际上是功能的用途……当然:如果您不喜欢方括号,您仍然可以对get()
使用方法,但是听起来像一个函数,它就像一个函数,所以它可能也是一个函数;-)
添加了()
和=
的唯一不同的完整示例:
fun main() {
val androidConfig = android {
buildToolsVersion = "28.0.3"
compileSdkVersion = 26
}
println(androidConfig.toConsolePrint())
}
fun android(block: Android.() -> Unit) = Android().apply(block)
class Android(var compileSdkVersion: Int = 0,
var buildToolsVersion: String = "") {
fun toConsolePrint() = "compileSDK: $compileSdkVersion build tools: $buildToolsVersion"
}