Kotlin 之 DSL详解

什么是DSL

Domain Special Language
DSL是领域特定语言,与通用语言不通,他只管他的领域,如:SQL、正则表达式

扩展函数

想理解DSL,首先得知道扩展函数。什么事扩展函数,直白一点就是在原有类的基础上不改变类,只增加一个函数,称为扩展函数。

class Test {

    fun fun1() {
        Test().fun2("fun2")
    }


}

fun Test.fun2(name: String) {

}

示例定义Test 类,只有一个fun1 函数,定义扩展函数fun2,接收一个String类型参数

熟悉了扩展函数,那就可以写一个比较火的代码生成布局的小例子


class Linear {
    fun createFragme(init: (Fragme) -> Unit) {
        init(Fragme())
    }

    fun createText(init: (Text) -> Unit) {
        init(Text())
    }
}

class Fragme {
    fun createText(init: (Text) -> Unit) {
        init(Text())
    }
}

class Text {}

fun creatLinear(init: (Linear) -> Unit) {
    init(Linear())
}

fun run() {
    creatLinear {
        it.createFragme {
            it.createText { }
        }
        it.createText { }
    }
}

伪代码很好理解,有三种view,其中两个是Layout,可以包含其他view。
这样创建布局是不是很爽,但缺点是调用函数要写 it ,不想写怎么办?
答案就是使用DSL

DSL

先看一个简单例子

fun linear(init: Linear.() -> Unit) {
    Linear().init()
}

入参还是一个函数,只不过这个函数前面加上了Linear. 并且去掉了入参

fun Test.fun2(name: String) {

}

仔细看 Linear.() 像什么,是不是和上面讲的定义扩展函数非常类似,只不过去掉了函数名,我们可以叫它 匿名扩展函数。好处就是可以在扩展函数的函数体中使用this调用被扩展类的函数,而this是可以省略的,从而达到省略 it 的目的。

简单例子中 Linear接收者类型 , 实例化的 Linear() 对象叫接收者对象

使用DSL 改造上面的例子

class Linear {
    fun fragme(init: Fragme.() -> Unit) {
        Fragme().init()
    }

    fun text(init: Text.() -> Unit) {
        Text().init()
    }
}

class Fragme {
    fun text(init: Text.() -> Unit) {
        Text().init()
    }
}

class Text {}

fun linear(init: Linear.() -> Unit) {
    Linear().init()
}

fun run(){
    linear { 
        fragme { 
            text {  }
        }
        text {  }
    }
}

是不是清晰了很多

推荐阅读更多精彩内容