Kotlin-小抄(十)Kotlin创建DSL

DSL简介
  • DSL (领域特定语言)指的是专注于特定问题领域的计算机语言,即对一个特定问题的方案模型更高层次的抽象表达,使之更加简单易懂。
  • DSL只是问题解决方案模型的外部封装,这个模型可能是一个API库,也可能是一个完整的框架等
  • 在Android中比较典型的例子使用DSL框架Anko来替代传统的xml(类似Flutter创建布局的方式)如下代码块:
UI {
    // AnkoContext
    verticalLayout {
        padding = dip(30)
        var title = editText {
            // editText 视图
            id = R.id.todo_title
            hintResource = R.string.title_hint
        }

        var content = editText {
            id = R.id.todo_content
            height = 400
            hintResource = R.string.content_hint
        }
        button {
            // button 视图
            id = R.id.todo_add
            textResource = R.string.add_todo
            textColor = Color.WHITE
            setBackgroundColor(Color.DKGRAY)
            onClick { _ -> createTodoFrom(title, content) }
        }
    }
}
DSL种类
内部DSL
  • 内部DSL是指与项目中是使用的通用目的编程语言紧密相关的DSL
外部DSL
  • 外部DSL是从零开始构建的语言,需要实现语法分析器,外部DSL与通用编程语言(GPL)类似,但是外部DSL更加专注于特定领域,创建 外部DSL和创建一种通用的百年城语言的过程是类似的,可以是编译型和解释型
Kotlin中的DSL支持
实现原理
  • 扩展函数、扩展属性
  • 带接收者的Lambda表达式(高阶函数)
  • invoke函数调用约定
实现集合类的流式Kotlin DSL

(可以模仿filter来实现)

// filter函数的入参是一个函数predicate:(T)->Boolean public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {     return filterTo(ArrayList<T>(), predicate) }

fun <T : Comparable<T>> List<T>.sort() {
    Collections.sort(this) // this代表调用函数的对象
}

@Test
fun testSort() {
    val list = listOf(1,7,10,5,6)
    list.sort()
    print(list)  // [1, 5, 6, 7, 10]
}
实现SQL风格的集合类DSL
data class Student(var name: String, var sex: String, var score: Int)


fun <E> List<E>.select(): List<E> = this


fun <E> List<E>.where(prediction: (E) -> Boolean): List<E> {
    val list = this
    val result = arrayListOf<E>()
    for (e in list) {
        if (prediction(e)) {
            result.add(e)
        }
    }
    return result
}


fun <E> List<E>.and(prediction: (E) -> Boolean) : List<E> {
    return where(prediction)
}


@Test
fun testSql() {
    val students = listOf(
        Student("w", "M", 90),
        Student("e", "M", 80),
        Student("r", "M", 60),
        Student("t", "M", 80),
        Student("y", "F", 100)
    )


    val  queryResult = students.select()
        .where { it.score >= 80 }
        .and {it.sex == "M"}


    print(queryResult)
    // [Student(name=w, sex=M, score=90), Student(name=e, sex=M, score=80), Student(name=t, sex=M, score=80)]
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wjxbless

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值