Kotlin学习(10)使用Kotlin创建DSL

as## 1. 什么是DSL
DSL(领域特定语言)指的是专注于特定问题领域的计算机语言。不同于通用的计算机语言(GPL),领域特定语言只用在某些特定的领域。

DSL语言能让我们以一种更优雅、更简洁的方式的方式来表达和解决领域问题。
简单来讲就是对一个特定的问题的方案模型更高层次的抽象表达,使其更加简单易懂。

DSL只是问题问题解决方案模型的外部包装,这个模型可能是一个 API库,也可能是一个完整的框架等。DSL提供了思考特定领域问题的模型语言。这使得我们可以更加简单、高效的解决问题。

一个典型的例子就是用于替代Android开发中布局XML文件的DSL框架 Anko,它使用基于Kotlin的DSL来声明Android UI组件,而不是传统的XML

1.1 内部DSL
内部DSL是指与项目中使用的通用目的编程语言紧密相关的一类DSL。它基于通用编程语言实现
框架或程序库的API是否满足内部DSL的关键特征之一就是 它是否有一个流畅的接口。这样就能够用短小的对象表达式去组织一个原本很长的表达式,使它读起来更加自然

1.2 外部DSL
和内部DSL相反,外部DSL是从零开始构建的语言,需要实现语法分析器。
通常情况下,我们只需要实现内嵌式DSL,因为它更容易构建,并且具有很多与外部DSL相同的优势

2. Kotlin的DSL特性支持

在Kotlin中创建DSL,一般主要使用下面3个特性:

  • 扩展函数、扩展属性
  • 带接受者的Lambda表达式
  • invoke 函数调用约定

其实就是要 重写invoke()

3. 实现集合类的流式Kotlin DSL

下面来创建一个给定文件名返回文件中每行文本字符串的流式API,代码风格是下面这样的:

fun main(args: Array<String>) {
    val lines = "src/main/resources/data.txt"
            .stream()
            .buffered()
            .reader("utf-8")
            .readLines()
     lines.forEach(::println)
}

//接下来来扩展函数:
    fun String.stream() = FileInputStream(this)

    fun FileInputStream.buffered() = BufferedInputStream(this)

    fun InputStream.reader(charset: String) = InputStreamReader(this, charset)

    fun Reader.readLines(): List<String> {
        val result = arrayListOf<String>()
        forEachLine {
            result.add(it)
        }
        return result
    }

4. 实现一个SQL风格的集合类DSL

我们来实现一个简单的在 Kotlin做 SQL操作的DSL

//创建一个学生类
data class Student(var name: String, var sex: String, var score: Int)

 val students = listOf(
            Student("Rikka","M",90),
            Student("xiaohu","F",76),
            Student("uzi","M",105),
            Student("karsa","F",50)
        )

接下来定义sql的查询方法:

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

    //参数是一个  入参为E,出参为Boolean的函数
    fun <E> List<E>.where(predicate: (E) -> Boolean): List<E> {
        val list = this
        val result = arrayListOf<E>()
        for (e in list) {
            if (predicate(e)) {
                result.add(e)
            }
        }
        return result
    }

    fun <E> List<E>.and(predicate: (E) -> Boolean): List<E> {
        return where(predicate)
    }
发布了248 篇原创文章 · 获赞 99 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/rikkatheworld/article/details/103039513