kotlin 1.2.71
I have the following DSL I am writing and want to get it as close to this sample as possible:
android {
compileSdkVersion 26
buildToolsVersion "28.0.3"
}
I am doing this using infix functions and lambda and receivers. Inside my DSL I have to use the it
keyword otherwise I can't get the infix function to work. Just wondering, if there was a way to do this?
Another question: In my infix function do I need to use it as an extension function and prefix it with the keyboard Android i.e. 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"
}
To clarify: you do not need the it
for the infix
to work. You could also just have written this
instead, e.g. this compileSdkVersion 26
.
Note also that it rather suffices to just have the following in place:
fun android(block: Android.() -> Unit) = Android().apply(block)
class Android(var compileSdkVersion: Int = 0,
var buildToolsVersion: String = "")
The usage then only differs by a =
to what you have shown:
val androidConfig = android {
buildToolsVersion = "28.0.3"
compileSdkVersion = 26
}
But the benefit is way bigger: much less code to maintain ;-)
Regarding the other point you mentioned, that you need to supply extension functions. You didn't need to. It suffices to just place the infix fun Android.buildToolsVersion
inside of the class Android
without the Android.
and it would have worked, e.g.:
class Android(var compileSdkVersion: Int = 0,
var buildToolsVersion: String = "") {
infix fun buildToolsVersion(buildToolsVersion: String) {
this.buildToolsVersion = buildToolsVersion
}
Now regarding consolePrint
. That looks also rather complicated to me. What about the following instead inside the class Android
?
fun toConsolePrint() = "compileSDK: $compileSdkVersion build tools: $buildToolsVersion"
That's what functions are actually used for... of course: if you do not like the brackets, you can still use your approach with the get()
, but it sounds like a function, it acts like a function, so it probably also is a function ;-)
The complete sample with only difference being added ()
and =
:
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"
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With