媒介
在这篇文章中,我们将学习怎样在您的 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。但是,在这里我们可以以两种差别的方式使用它。两者如下,
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 的方法。
为此,让我们将 textView 视为 UI 元素。在那,我们使用如下,
textView.text = "MindOrks"textView.setOnClickListener { } textView.setTextColor(Color.BLACK)但是要通过我们使用的 DSL 使用它,
textView.apply { text = "MindOrks" setOnClickListener { } textColor(Color.BLACK)}我们使用apply在任何 UI元素中创建 DSL。
在我们使用的 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 的方式。
作者:Himanshu Singh
链接:https://blog.mindorks.com/mastering-kotlin-dsl-in-android-step-by-step-guide
|