DSL介绍
DSL一般用于项目的构建脚本,比如gradle配置文件
使用步骤
使用了高阶函数
扩展函数
带接收者函数的函数参数
DSL简单对象
package com.wzh
fun main() {
val person2 = person {
name = "张三"
age = 20
address {
addressName = "广东"
}
}
println(person2)//Person2(name=张三, age=20, address=Address(addressName=广东))
}
fun Person2.address(block: Address.() -> Unit) {
this.address = Address().apply(block)
//this.address = Address().also{it.block()}
/*this.address = Address().let {
it.block()
it
}*/
/*this.address = with(Address()){
block()
this
}*/
/*this.address = Address().run {
block()
this
}*/
}
fun person(block: Person2.() -> Unit): Person2 {
val person2 = Person2()
person2.block()
return person2
}
data class Person2(var name: String = "", var age: Int = 0, var address: Address? = null)
data class Address(var addressName: String = "")
DSL使用集合对象
fun main() {
val p = person {
name = "张三"
age = 30
addresses {
address {
addressName = "广东"
}
address {
addressName = "北京市"
}
}
}
println(p)
}
fun person(b: Person.() -> Unit): Person {
return Person().apply(b)
}
fun Person.addresses(b: ArrayList<PersonAddress>.() -> Unit) {
addresses = ArrayList<PersonAddress>().apply(b)
}
fun ArrayList<PersonAddress>.address(b: PersonAddress.() -> Unit) {
this.add(PersonAddress().apply(b))
}
data class Person(var name: String = "", var age: Int = 0, var addresses: List<PersonAddress>? = null)
data class PersonAddress(var addressName: String = "")
DSL限制变量的作用域
限制作用域,让变量的使用更加安全
定义注解
@DslMarker
annotation class MY
将注解应用到类上
@MY
data class Person(var name: String = "", var age: Int = 0, var addresses: List<PersonAddress>? = null)
@MY
data class PersonAddress(var addressName: String = "")
fun main() {
val p = person {
name = "张三"
age = 30
addresses {
address {
addressName = "广东"
}
address {
addressName = "北京市"
//name=""//限制作用域后,在这里就无法使用外层的作用域了
}
}
}
println(p)
}
fun person(b: Person.() -> Unit): Person {
return Person().apply(b)
}
fun Person.addresses(b: ArrayList<PersonAddress>.() -> Unit) {
addresses = ArrayList<PersonAddress>().apply(b)
}
fun ArrayList<PersonAddress>.address(b: PersonAddress.() -> Unit) {
this.add(PersonAddress().apply(b))
}
@MY
data class Person(var name: String = "", var age: Int = 0, var addresses: List<PersonAddress>? = null)
@MY
data class PersonAddress(var addressName: String = "")
@DslMarker
annotation class MY