前言
在这篇文章中,我们将学习如何在您的 Android 项目中编写 Kotlin DSL。
这个文章会很长,所以花点时间,让我们一起来写你的 DSL。我们将讨论以下主题,
- 什么是简单英语中的 DSL?
- 您使用任何 DSL 吗?
- 为什么我们使用 DSL?
- 我们如何编写自己的 DSL
- 基本示例说明。
那么让我们开始吧。
什么是 DSL?
维基百科的定义说,
领域特定语言( DSL) 是专门针对特定应用领域的计算机语言。这与广泛适用于跨领域的通用语言(GPL)形成对比。
喜欢认真吗?
一般而言,DSL 为您提供了任何特定语言的灵活工具,以利用特定编程语言提供的功能。
您使用任何 DSL 吗?
如果您是一名 android 开发人员并且在您的项目中使用 kotlin,您可能会有意或无意地在您的项目中使用 DSL?你能想出一个例子吗?
让我帮你,你有没有写过类似的代码,
yourlist.forEach {
//your code is here
}
上面的例子是在 Kotlin 的列表中使用forEach。forEach is kotlin 是 DSL 的一个例子
为什么我们使用 DSL?
我们应该使用 DSL 来简化和提高应用程序的复杂性,并使代码更具可读性。
我们如何编写自己的 DSL?
在开始编写我们自己的 DSL 之前,我们需要了解带有接收器的 lambda。
但也让我简要概述一下 lambda with receiver
假设我们有一个函数 buildString,
fun buildString(action: (StringBuilder).() -> Unit): String {
val stringBuilder = StringBuilder()
action(stringBuilder)
return stringBuilder.toString()
}
在这里,我们有一个函数buildString,它将动作(它是一个函数)作为参数。此处的action函数以StringBuilder作为参数,函数buildString以 String 作为返回类型。
现在,要使用我们编写的buildString ,
buildString {
append("<")
append("MindOrks")
append(">")
}
我们在这里使用 Kotlin 的属性来传递与 StringBuilder 相关的属性,因为我们在buildString函数中使用了扩展函数的强大功能。
我们还可以使用创建自定义 DSL,
中缀
在 Kotlin 中,中缀帮助我们创建自定义 DSL,类似于我们用英语编写的方式。例如,
在英语中,我们说“1加2”来求和或求差,我们说“1减2”。使用中缀调用可以在 Kotin 中实现类似的事情。
为了创建一个中缀来添加我们使用的数字,
infix fun Int.plus(number: Int) = this + number
在这里,我们创建了一个 Int 的扩展函数,加上它接受一个数字并返回这个 + 数字的总和。这是应用函数的数字。
所以,要使用我们使用的这个中缀函数,
val output = 1 plus 2
在上面的代码中,我们使用我们创建加号的中缀函数来生成输出。当我们在 Logcat 中打印它时,它会打印3作为总和。
这是因为我们创建了一个中缀扩展函数来使用加号文本代替“ + ”,我们将其用作传统方式。
同样,如果我们想让中缀函数减号,我们使用
infix fun Int.minus(number: Int) = this - number
为了使用它,我们使用,
val output = 1 minus 2
中缀使代码具有可读性并且非常有序,任何人都可以阅读。因此,如果任何对编程一无所知的人也可以说这是对两个数字进行加法或减法。
调用
在调用中,运算符允许将任何对象作为函数调用。在这里,让我们创建一个名为Student的类,
class Student {
operator fun invoke(student: Student.() -> Unit) = student
fun addName(name: String) {
//implementation
}
fun addMarks(marks: Int) {
//implementation
}
}
在类中,我们创建了一个函数调用,它接受一个学生类型的参数并返回学生本身。所以,这里我们可以在student本身的对象中使用Student类的所有方法。
现在,要使用 Class,我们仍然会像在 Kotlin 中一样创建对象,
val student = Student()
现在你可以看到我们有另一个函数叫做addName 和addMarks**我们将把它用作 DSL。但是,在这里我们可以以两种不同的方式使用它。两者如下,
- 类型 - 1(传统方式)
student.addName("MindOrks")
student.addMarks(100)
上面的代码就像我们以前在 Android 中做的旧的传统方式。2.DSL方式
student {
addName("MindOrks")
addMarks(100)
}
在这里,我们使用 Kotlin DSL。如果你注意到了,我们有类似的 lambda,
Student.() -> Unit
如果你注意到了,我们在那里有一个.()。它指定 lambda 有一个接收器,要使用它,我们需要创建一个类的构造。这就是您可以使用调用来创建 DSL 的方式。
通过以上方式,您可以在 Kotlin 中创建您赢得的 DSL。
现在,让我们讨论 Android 中 DSL 的用例和示例。
- 数据类
在此,让我们讨论如何创建数据类的 DSL。考虑我们有一个数据类 Student
data class Student(
var name: String? = null,
var age: Int? = null,
var marks: Int? = null
)
在此,如果我们使用我们编写的数据类,
val student = Student(
"MindOrks",
20,
30
)
现在要在 DSL 中转换上述代码,
现在我们将创建一个新的 lambda,如下所示,
fun student(student: Student.() -> Unit): Student = Student().apply(student)
在上面的代码中,
我们有一个接收器,参数为 student 并将其用作我们使用的 DSL,
val student = student {
name = "MindOrks"
age = 20
marks = 30
}
这就是我们可以将数据类转换为 DSL 的方法。
- UI 元素
为此,让我们将 textView 视为 UI 元素。在那,我们使用如下,
textView.text = "MindOrks"
textView.setOnClickListener {
}
textView.setTextColor(Color.BLACK)
但是要通过我们使用的 DSL 使用它,
textView.apply {
text = "MindOrks"
setOnClickListener {
}
textColor(Color.BLACK)
}
我们使用apply在任何 UI元素中创建 DSL。
- JSON
在我们使用的 Android 中创建 JSON,
val jsonObject = JSONObject()
jsonObject.put("name","MindOrks")
jsonObject.put("age",20)
这是创建 JSON 对象的传统方式。
现在,让我们看看如何创建 DSL 来创建 JSON。首先,我们将创建一个类并使用 JSONObject() 对其进行扩展,
class Json() : JSONObject() {
}
现在,我们将使用带有接收器的 lambda 构造函数
constructor(json: Json.() -> Unit) : this() {
this.init()
}
将使用中缀创建一个泛型来向 JSON 对象添加值。
看起来像,
infix fun <T> String.to(value: T) {
put(this, value)
}
在这里,它将使用字符串键放置值,而值将使用“ to”的类型。
现在,完整的类文件看起来像,
class Json() : JSONObject() {
constructor(json: Json.() -> Unit) : this() {
this.json()
}
infix fun <T> String.to(value: T) {
put(this, value)
}
}
为了在 Activity 文件中使用它,我们使用刚刚创建的 DSL 创建 JSON,
val json = Json {
"name" to "MindOrks"
"age" to 20
}
这里,
- to是我们为将值放入 JSON 对象而创建的中缀。
- JSON 是我们创建的类,它使用键和值来创建 JSON 对象。
当我们在 Logcat 中打印它时,我们得到以下输出,
{"name":"MindOrks","age":20}
这就是您可以在 kotlin 代码中创建 DSL 的方式。