什么是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 { }
}
}
是不是清晰了很多