kotlin

学起来:Kotlin DSL模拟gradle构建方法

2020-06-12  本文已影响0人  InnerNight

简介

想要了解Kotlin DSL可以参考这个文章:Kotlin 之美—DSL篇
内网ata也有这样一篇文章:https://www.atatech.org/articles/138936
KotlinDSL是什么?能用来干什么?都可以从这两篇文章中获得答案。
而最近谷歌现在也在推Kotlin DSL来替代groovy作为gradle的语言。其实Kotlin设计的思路上主要受到了同为JVM语言的groovy、Scala影响,因此很多用法和写法都很相似。而Kotlin DSL, 则把 Kotlin 的语法糖演绎得淋漓尽致。学习Kotlin DSL可以帮助更好的理解Kotlin中的各种语法,用Kotlin DSL来模拟gradle的构建过程,则既可以学习Kotlin DSL,又复习下gradle的构建。

示例

首先看代码:

apply("android")

task {
    println("debug task run")
}

task("test") {
    println("test task run")
    doFirst {
        println("test task do first")
    }
    doLast {
        println("test task do last")
    }
}

dependencies {
    compile("com.test.a")
    implementation("com.test.b")
}

对于安卓开发者来说,这段代码会显得很熟悉,很像gradle中的配置,但有一些不同。但其实,这段代码并不是groovy,而是kotlin实现的代码,甚至这段代码并不是真正的gradle配置,而是我通过kotlin实现的一段mock gradle代码,这里面调用的所有方法都是调用了我自己实现的函数。代码链接 奉上,可以参考其中的方法实现。这段代码的运行结果是这样的:

---------------- project initialization ----------------
running in context: mock jvm
---------------- project configuration ----------------
abctest
apply plugin: java
debug task run
test task run
add compile dependency: com.test.a
add implementation dependency: com.test.b
---------------- project execution ----------------
configure dependency: com.test.a
configure dependency: com.test.b
execute task: 
start executing...
executing task
execute task: test
start executing...
test task do first
executing task
test task do last

从输出结果来看,基本mock了gradle的三个步骤,有兴趣的同学可以对照gradle的构建流程理解一下,这里不做详细的介绍。
而通过这个示例可以看到,Kotlin DSL相比原API式的调用,结构更加清晰、更接近自然语言的风格。

实现细节

如何去实现这样一个接近自然语言的kotlin dsl?具体可以参考源码中的Project.kt, 下面介绍几个用的比较多的语言特性,包括:

  1. 带Receiver的lambda语句;
    这种高阶函数的声明方式赋予了lambda类似作用域一样的空间,代码示例:
// 声明接收者
fun kotlinDSL(block:StringBuilder.()->Unit){
  block(StringBuilder("Kotlin"))
}

// 调用高阶函数
kotlinDSL {
  // 这个 lambda 的接收者类型为StringBuilder
  append(" DSL")
  println(this)
}
  1. 中缀调用;
    在Kotlin中如果函数的参数只有一个,可以使用infix关键字来支持中缀调用。这种语法的支持让我们的代码从函数调用更加像自然语言,代码示例:
"key" to "value"
// 等价于
"key.to("value")

// to的声明,重点在infix关键字
infix fun Any.to(that:Any) = Pair(this,that)
  1. invoke约定操作符重载;
    这种语法可以让你像调用函数一样调用对象,代码示例:
class Person(val name:String){
    operator fun invoke(){
        println("my name is $name")
    }
}

>> val person = Person("geniusmart")
>> person()
my name is geniusmart

除了上面提到的三种语法糖,还有类似lambda参数、扩展函数等Kotlin语言特性也在DSL的实现中得到了使用,具体可以看代码,相信可以从中体会到很多Kotlin的妙用。也欢迎大家多多讨论更多Kotlin的用法。

上一篇下一篇

猜你喜欢

热点阅读