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)]
}
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页