"Kotin Minimalist Tutorial" Chapter 14 Using Kotlin DSL

Chapter 14 Using Kotlin DSL

We have seen the powerful features of Kotlin DSL in the previous chapters. For example, Gradle's configuration file build.gradle (Groovy), as well as the Gradle Script Kotlin (Kotlin), Anko (Kotlin), etc. that we mentioned earlier, are all DSLs. We can see that using the DSL programming style can make the program simpler, cleaner, more intuitive and concise. Of course, we can also create our own DSL.

In this chapter, let us learn about DSL in Kotlin.

We have seen in the last chapter that the following nested DSL style code is used in Android to replace the XML style view file

        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) }
                }
            }
        }

Compared with the XML-style DSL (XML is essentially a DSL), the DSL style using native programming languages ​​(such as Kotlin) is obviously simpler, cleaner, and more flexible.

What is the programming style of Kotlin DSL? And what is the principle behind it? Let me discuss it together below.

What is DSL

DSL (Domain-Specific Language) refers to a computer language (domain-specific language) that focuses on a specific problem domain. Different from general computer language (GPL), domain-specific languages ​​are only used in certain domains.

"Domain" may specifically refer to a certain industry, such as insurance, education, aviation, medical, etc.; it may also refer to a method or technology, such as JavaEE, .NET, database, service, messaging, architecture, and domain-driven design. The purpose of developing the DSL language is that we have to face a series of challenges in the field in a more elegant and concise way. This is possible because this language is just enough to solve the only series of challenges in the field, not much at all, and not at all, just right.

For example, the HTML language used to display web pages. A more typical example is Gradle, which is based on Ant and Maven and uses a Groovy-based DSL to declare the project build configuration build.gradle instead of traditional XML.

To put it simply, DSL is a higher-level abstract expression (domain language) of a solution model for a specific problem (limited expression ability), making it easier to understand (easy to understand semantics and clear semantic model).

DSL is just an external package of the problem solution model. This model may be an API library or a complete framework. DSL provides a model language for thinking about problems in a specific domain, which allows us to solve problems more simply and efficiently. DSL focuses on a specific field, is simple and easy to understand, and has minimal but complete functions. DSL makes it easier for us to understand and use models.

DSL is divided into internal DSL and external DSL. For example, Gradle, Anko, etc. are all internal DSLs we created using common programming languages ​​(Java and Kotlin).

Internal DSL

Internal DSL refers to a type of DSL closely related to the general purpose programming language (Java, C#, or Ruby) used in the project. It is implemented based on a general programming language.

For example, the Rails framework is called a Ruby-based DSL for managing web applications developed by Ruby. One of the reasons why Rails is called DSL is that Rails applies some features of the Ruby language, making Rails-based programming look different from general-purpose Ruby programming.

According to Martin Fowler and Eric Evans, one of the key characteristics of whether the framework or library API meets the internal DSL is whether it has a fluent interface. In this way, you can use short object expressions to organize an otherwise long expression, making it more natural to read.

External DSL

The external DSL is similar to the General Programming Language (GPL), but the external DSL is more focused on specific areas.

The process of creating an external DSL is similar to creating a general-purpose programming language, it can be compiled or interpreted. It has a formal grammar and only allows the use of well-defined keywords and expression types. The compiled DSL usually does not directly produce executable programs (but it does).

In most cases, the external DSL can be converted into a resource compatible with the operating environment of the core application, or it can be converted into a general purpose programming language for building the core application. For example, the object-relational mapping file used in Hibernate is an instance converted into a resource by an external DSL.

Tip: For a detailed introduction to DSL, please refer to the book "Domain Specific Languages" (Martin Fowler).

Kotlin's DSL feature support

Many modern languages ​​provide some advanced methods for creating internal DSLs, and Kotlin is no exception.

To create a DSL in Kotlin, generally use the following two features:

  • Extended functions, extended attributes
  • Lambda expression with receiver (higher-order function)

Such as the example of the above UI {...}code, we briefly described as follows Examples

Function name Function signature instruction manual
UI fun Fragment.UI(init: AnkoContext.() -> Unit):AnkoContext The extension function of android.support.v4.app.Fragment; the input parameter init is a function literal with a receiver, and what we directly pass in is a Lambda expression
verticalLayout inline fun ViewManager.verticalLayout(init: _LinearLayout.() -> Unit): LinearLayout android.view.ViewManager extension function

Use kotlinx.html DSL to write front-end code

In order to deepen the understanding of the practicality of Kotlin DSL, we will introduce another
DSL about HTML in Kotlin in this section : kotlinx.html.

kotlinx.html is a DSL that can be used to build HTML in web applications. It can be used as a substitute for traditional template systems (such as JSP, FreeMarker, etc.).

kotlinx.html provides DSLs for the kotlinx-html-jvm and kotlinx-html-js libraries respectively, which are used to directly use Kotlin code in the JVM and browser (or other javascript engines) to build html, which directly liberates the original HTML Tabbed front-end code. In this way, we can also use Kotlin to start HTML pages in the traditional sense. Kotlin Web programming will be simpler and purer.

Tip: For more information about kotlinx.html, please refer to its Github address: https://github.com/Kotlin/kotlinx.html

To use kotlinx.html first add dependencies

dependencies {
    def kotlinx_html_version = "0.6.3"
    compile "org.jetbrains.kotlinx:kotlinx-html-jvm:${kotlinx_html_version}"
    compile "org.jetbrains.kotlinx:kotlinx-html-js:${kotlinx_html_version}"
    ...
}

The latest version of kotlinx.html is published on the https://jcenter.bintray.com/ warehouse, so let’s add the warehouse configuration

repositories {
    maven { url 'https://jitpack.io' }
    mavenCentral()
    jcenter() // https://jcenter.bintray.com/ 仓库
    maven { url "https://repo.spring.io/snapshot" }
    maven { url "https://repo.spring.io/milestone" }
}

Let's write an example of a minimalist Baidu homepage. The front-end HTML code of this page is as follows:

<!DOCTYPE html>
<html lang=zh-CN>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name=viewport content="width=device-width,initial-scale=1">
    <title>百度一下</title>
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <link href="dsl.css" rel="stylesheet">
    <script src="dsl.js"></script>
</head>
<body>
<div class="container">
    <div class="ipad center">
        ![](http://upload-images.jianshu.io/upload_images/1233356-49a0fecdc8bfa9cf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    </div>

    <form class="form">
        <input id="wd" class="form-control ipad">
        <button id="baiduBtn" type="submit" class="btn btn-primary form-control ipad">百度一下</button>
    </form>
</div>
</body>
</html>

Among them, the content of the dsl.css file is as follows

.ipad {
    margin: 10px
}

.center {
    text-align: center;
}

The content of the dsl.js file is as follows

$(function () {
    $('#baiduBtn').on('click', function () {
        var wd = $('#wd').val()
        window.open("https://www.baidu.com/s?wd=" + wd)
    })
})

Above we are usually using HTML+JS+CSS to write front-end pages. Now we reimplement the HTML part of the code with Kotlin's DSL kotlinx.html.

We first create a new Kotlin + Spring Boot project, and then directly write the Kotlin view class HelloDSLView, the code is as follows:

package com.easy.kotlin.chapter14_kotlin_dsl.view

import kotlinx.html.*
import kotlinx.html.stream.createHTML
import org.springframework.stereotype.Service

/**
 * Created by jack on 2017/7/22.
 */
@Service
class HelloDSLView {
    fun html(): String {
        return createHTML().html {
            head {
                meta {
                    charset = "utf-8"
                    httpEquiv = "X-UA-Compatible"
                    content = "IE=edge"
                }
                title("百度一下")
                link {
                    href = "https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css"
                    rel = "stylesheet"
                }
                script {
                    src = "https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"
                }
                link {
                    href = "dsl.css"
                    rel = "stylesheet"
                }
                script {
                    src = "dsl.js"
                }
            }

            body {
                div(classes = "container") {
                    div(classes = "ipad center") {
                        img {
                            src = "https://www.baidu.com/img/bd_logo1.png"
                            width = "270"
                            height = "129"
                        }
                    }

                    form(classes = "form") {
                        input(InputType.text, classes = "form-control ipad") {
                            id = "wd"
                        }
                        button(classes = "btn btn-primary form-control ipad") {
                            id = "baiduBtn"
                            type = ButtonType.submit
                            text("百度一下")

                        }
                    }

                }
            }
        }
    }
}

In contrast, our DSL style is more concise and elegant than native HTML. The key is that our HTML is written in Kotlin, which means that our HTML code is no longer a simple static front-end code. We can directly use the back-end interface to return data to assign values ​​to HTML elements. We also have (of course, completely surpassed) the various judgments, loops and other grammatical functions of view template engines such as JSP and Freemarker, because we Directly use HTML code written in a powerful programming language Kotlin.

Then, we can directly call our Kotlin view code directly in the code of the controller layer:

@Controller
class HelloDSLController {
    @Autowired
    var helloDSLView: HelloDSLView? = null

    @GetMapping("hello")
    fun helloDSL(model: Model): ModelAndView {
        model.addAttribute("hello", helloDSLView?.html())
        return ModelAndView("hello")
    }
}

For the sake of simplicity, we borrow Freemarker as the view parsing engine, but it is only responsible for transmitting our Kotlin view code intact. The hello.ftl code is as follows:

${hello}

Our source code directory is as follows

── src
    ├── main
    │   ├── java
    │   ├── kotlin
    │   │   └── com
    │   │       └── easy
    │   │           └── kotlin
    │   │               └── chapter14_kotlin_dsl
    │   │                   ├── Chapter14KotlinDslApplication.kt
    │   │                   ├── controller
    │   │                   │   └── HelloDSLController.kt
    │   │                   └── view
    │   │                       └── HelloDSLView.kt
    │   └── resources
    │       ├── application.properties
    │       ├── banner.txt
    │       ├── static
    │       │   ├── dsl.css
    │       │   ├── dsl.js
    │       │   └── hello.html
    │       └── templates
    │           └── hello.ftl
    └── test
        ├── java
        ├── kotlin
        │   └── com
        │       └── easy
        │           └── kotlin
        │               └── chapter14_kotlin_dsl
        │                   └── Chapter14KotlinDslApplicationTests.kt
        └── resources

Then, start and run the SpringBoot application, visit http://127.0.0.1:8888/hello in the browser, we can see the following output interface:

Screenshot 2017-07-23 03.53.07.png

This is the subtlety of DSL. We can try to use kotlinx.html to write the front-end code of the Kotlin language later. When doing Web development, we usually use HTML + template engines (Velocity, JSP, Freemarker, etc.) to integrate the front-end and back-end code, which makes us sometimes feel embarrassed. To learn the syntax of the template engine, we have to deal with the front-end HTML Messy template engine tags, variables and other fragments of code in the code.

The situation of using Kotlin DSL to write HTML code will be completely different. We will regain the fun of front-end and back-end integrated coding (no longer a template engine with front-end HTML, all kinds of strange #, <#>, ${} template languages Tags), we directly moved the more elegant and simple DSL style HTML code to the back end. At the same time, the elements in the HTML will directly interact with the back end data seamlessly, and this is done only by Kotlin (of course, the basic semantics of the DSL in the corresponding field The model still needs to be learned).

Tip: The source code of the project in this section: https://github.com/EasyKotlin/chapter14_kotlin_dsl

Implement a minimal http DSL

We now basically know what a DSL in Kotlin looks like. But how are these DSLs implemented? In this section, we will learn the basic principles behind creating a DSL by implementing a minimal http DSL.

Here we do a simple encapsulation of OkHttp to implement a DSL similar to the Ajax http request in jquery.

OkHttp is a mature and powerful network library. OkHttp has been used to replace the original HttpURLConnection in the Android source code. Many well-known frameworks such as Picasso and Retrofit also use OkHttp as the underlying framework.

Tip: For more information about the use of OkHttp, please refer to: http://square.github.io/okhttp/

Create Kotlin Gradle project

We first use IDEA to create a Kotlin Gradle project

Screenshot 2017-07-23 18.43.04.png

Then, configure dependencies in build.gradle

    compile 'com.github.ReactiveX:RxKotlin:2.1.0'
    compile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.8.1'
    compile group: 'com.alibaba', name: 'fastjson', version: '1.2.35'

Among them, RxKotlin is the support library of the ReactiveX framework for the Kotlin language. Here we mainly use RxKotlin for asynchronous processing of request callbacks.

We are using'com.github.ReactiveX:RxKotlin:2.1.0', this library is on https://jitpack.io, so we add the jitpack repository in the repositories configuration

repositories {
    maven { url 'https://jitpack.io' }
    ...
}

RxKotlin

ReactiveX is the abbreviation of Reactive Extensions, generally abbreviated as Rx. It was originally an extension of LINQ. It was developed by a team led by Microsoft's architect Erik Meijer and was open sourced in November 2012.

Rx extends the observer mode to support data and event sequences. Rx is a programming model whose goal is to provide a consistent programming interface to help developers deal with asynchronous I/O (non-blocking) data streams more conveniently.

The Rx library supports .NET, JavaScript and C++. Rx has become more and more popular in recent years and now supports almost all popular programming languages. A list of languages ​​is as follows:

Programming languages ​​supported by Rx Project homepage
Java RxJava: https://github.com/ReactiveX/RxJava
JavaScript RxJS:https://github.com/ReactiveX/rxjs
C# Rx.NET:https://github.com/Reactive-Extensions/Rx.NET
C#(Unity) UniRx:https://github.com/neuecc/UniRx
Scala RxScala:https://github.com/ReactiveX/RxScala
Clojure RxClojure:https://github.com/ReactiveX/RxClojure
C++ RxCpp:https://github.com/Reactive-Extensions/RxCpp
take RxLua:https://github.com/bjornbytes/RxLua
Ruby Rx.rb:https://github.com/Reactive-Extensions/Rx.rb
Python: RxPY:https://github.com/ReactiveX/RxPY
Go RxGo:https://github.com/ReactiveX/RxGo
Groovy RxGroovy:https://github.com/ReactiveX/RxGroovy
JRuby RxJRuby:https://github.com/ReactiveX/RxJRuby
Kotlin RxKotlin:https://github.com/ReactiveX/RxKotlin
Swift RxSwift:https://github.com/kzaher/RxSwift
PHP RxPHP:https://github.com/ReactiveX/RxPHP
Elixir reaxive:https://github.com/alfert/reaxive
Dart RxDart:https://github.com/ReactiveX/rxdart

Most of the language libraries of Rx are maintained by the organization ReactiveX. Rx's more popular libraries include RxJava/RxJS/Rx.NET, etc. Of course, RxKotlin will become more popular in the future.

Tip: Rx's community website is: http://reactivex.io/. Github address: https://github.com/ReactiveX/

Http request object package class

First, we design the Http request object package class as follows

class HttpRequestWrapper {

    var url: String? = null

    var method: String? = null

    var body: RequestBody? = null

    var timeout: Long = 10

    internal var success: (String) -> Unit = {}
    internal var fail: (Throwable) -> Unit = {}

    fun success(onSuccess: (String) -> Unit) {
        success = onSuccess
    }

    fun error(onError: (Throwable) -> Unit) {
        fail = onError
    }
}

The member variables and functions of HttpRequestWrapper are described in the following table

member Description
url Request url
method Request methods, such as Get, Post, etc., are not case sensitive
body Request header, for simplicity, we directly use OkHttp's RequestBody type
timeout The timeout time is ms, we set the default value to 10s
success Function variable for successful request
fail Function variable for which the request failed
fun success(onSuccess: (String) -> Unit) Request success callback function
fun error(onError: (Throwable) -> Unit) Request failed callback function

http execution engine

We directly call OkHttp's Http request API

private fun call(wrap: HttpRequestWrapper): Response {

    var req: Request? = null
    when (wrap.method?.toLowerCase()) {
        "get" -> req = Request.Builder().url(wrap.url).build()
        "post" -> req = Request.Builder().url(wrap.url).post(wrap.body).build()
        "put" -> req = Request.Builder().url(wrap.url).put(wrap.body).build()
        "delete" -> req = Request.Builder().url(wrap.url).delete(wrap.body).build()
    }

    val http = OkHttpClient.Builder().connectTimeout(wrap.timeout, TimeUnit.MILLISECONDS).build()
    val resp = http.newCall(req).execute()
    return resp
}

It returns the response object Response of the request.

The unit we OkHttpClient.Builder().connectTimeout(wrap.timeout, TimeUnit.MILLISECONDS).build()set the timeout period in is TimeUnit.MILLISECONDS.

我们通过wrap.method?.toLowerCase()处理请求方法的大小写的兼容。

使用 RxKotlin 完成请求响应的异步处理

我们首先新建一个数据发射源:一个可观察对象(Observable),作为发射数据用

    val sender = Observable.create<Response>({
        e ->
        e.onNext(call(wrap))
    })

其中,e 的类型是 io.reactivex.Emitter (发射器),它的接口定义是

public interface Emitter<T> {
    void onNext(@NonNull T value);
    void onError(@NonNull Throwable error);
    void onComplete();
}

其方法功能简单说明如下:

方法 功能
onNext 发射一个正常值数据(value)
onError 发射一个Throwable异常
onComplete 发射一个完成的信号

这里,我们通过调用onNext方法,把 OkHttp 请求之后的响应对象Response 作为正常值发射出去。

然后我们再创建一个数据接收源:一个观察者(Observer)

    val receiver: Observer<Response> = object : Observer<Response> {
        override fun onNext(resp: Response) {
            wrap.success(resp.body()!!.string())
        }

        override fun onError(e: Throwable) {
            wrap.fail(e)
        }

        override fun onSubscribe(d: Disposable) {
        }

        override fun onComplete() {
        }

    }

receiver 的 onNext 函数接收 sender 发射过来的数据 Response, 然后我们在函数体内,调用这个响应对象,给 wrap.success 回调函数进行相关的赋值操作。同样的,onError 函数中也执行相应的赋值操作。

最后,通过 subscribe 订阅函数来绑定 sender 与 receiver 的关联:

sender.subscribe(receiver)

作为接收数据的 receiver (也就是 观察者 (Observer) ),对发送数据的 sender (也就是可被观察对象( Observable)) 所发射的数据或数据序列作出响应。

这种模式可以极大地简化并发操作,因为它创建了一个处于待命状态的观察者,在未来某个时刻响应 sender 的通知,而不需要阻塞等待 sender 发射数据。这个很像协程中的通道编程模型。

DSL主函数 ajax

我们的ajax DSL主函数设计如下:

fun ajax(init: HttpRequestWrapper.() -> Unit) {
    val wrap = HttpRequestWrapper()
    wrap.init()
    doCall(wrap)
}

其中,参数init: HttpRequestWrapper.() -> Unit 是一个带接收者的函数字面量,它的类型是init = Function1<com.kotlin.easy.HttpRequestWrapper, kotlin.Unit>。 HttpRequestWrapper是扩展函数init()的接收者,点号 . 是扩展函数修饰符。

我们在函数体内直接调用了这个函数字面量 wrap.init() 。这样的写法可能比较难以理解,这个函数字面量 init 的调用实际上是 init.invoke(wrap) ,就是把传入 ajax 的函数参数直接传递给 wrap 。为了更简单的理解这个 init 函数的工作原理,我们通过把上面的 ajax 函数的代码反编译成对应的 Java 代码如下:

   public static final void ajax(@NotNull Function1 init) {
      Intrinsics.checkParameterIsNotNull(init, "init");
      HttpRequestWrapper wrap = new HttpRequestWrapper();
      init.invoke(wrap);
      doCall(wrap);
   }

也就是说,ajax 函数的一个更容易理解的写法是

fun ajax(init: HttpRequestWrapper.() -> Unit) {
    val wrap = HttpRequestWrapper()
    init.invoke(wrap)
    doCall(wrap)
}

我们在实际应用的时候,可以直接把 init 写成Lambda 表达式的形式,因为接收者类型HttpRequestWrapper 可以从上下文推断出来。

我们这样调用 ajax 函数:

ajax {
    url = testUrl
    method = "get"
    success {
        string ->
        println(string)
        Assert.assertTrue(string.contains("百度一下"))
    }
    error {
        e ->
        println(e.message)
    }
}

下面是几个测试代码示例:

package com.kotlin.easy

import com.alibaba.fastjson.JSONObject
import okhttp3.MediaType
import okhttp3.RequestBody
import org.junit.Assert
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4

/**
 * Created by jack on 2017/7/23.
 */

@RunWith(JUnit4::class)
class KAjaxTest {

    @Test fun testHttpOnSuccess() {
        val testUrl = "https://www.baidu.com"
        ajax {
            url = testUrl
            method = "get"
            success {
                string ->
                println(string)
                Assert.assertTrue(string.contains("百度一下"))
            }
            error {
                e ->
                println(e.message)
            }
        }

    }

    @Test fun testHttpOnError() {
        val testUrl = "https://www2.baidu.com"

        ajax {
            url = testUrl
            method = "get"
            success {
                string ->
                println(string)
            }
            error {
                e ->
                println(e.message)
                Assert.assertTrue("connect timed out" == e.message)
            }
        }
    }


    @Test fun testHttpPost() {
        var json = JSONObject()
        json.put("name", "Kotlin DSL Http")
        json.put("owner", "Kotlin")
        val postBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json.toString())
        ajax {
            url = "saveArticle"
            method = "post"
            body = postBody
            success {
                string ->
                println(string)
            }
            error {
                e ->
                println(e.message)
            }
        }
    }


    @Test fun testLambda() {
        val testUrl = "https://www.baidu.com"

        val init: HttpRequestWrapper.() -> Unit = {
            this.url = testUrl
            this.method = "get"
            this.success {
                string ->
                println(string)
                Assert.assertTrue(string.contains("百度一下"))
            }
            this.error {
                e ->
                println(e.message)
            }
        }
        ajax(init)
    }

到这里,我们已经完成了一个极简的 Kotlin Ajax DSL。

本节工程源码: https://github.com/EasyKotlin/chatper14_kotlin_dsl_http

本章小结

相比于Java,Kotlin对函数式编程的支持更加友好。Kotlin 的扩展函数和高阶函数(Lambda 表达式),为定义Kotlin DSL提供了核心的特性支持。

使用DSL的代码风格,可以让我们的程序更加直观易懂、简洁优雅。如果使用Kotlin来开发项目的话,我们完全可以去尝试一下。


Kotlin开发者社区

专注分享 Java、 Kotlin、Spring/Spring Boot、MySQL、redis、neo4j、NoSQL、Android、JavaScript、React、Node、函数式编程、编程思想、"高可用,高性能,高实时"大型分布式系统架构设计主题。

High availability, high performance, high real-time large-scale distributed system architecture design

分布式框架:Zookeeper、分布式中间件框架等
分布式存储:GridFS、FastDFS、TFS、MemCache、redis等
分布式数据库:Cobar、tddl、Amoeba、Mycat
云计算、大数据、AI算法
虚拟化、云原生技术
分布式计算框架:MapReduce、Hadoop、Storm、Flink等
分布式通信机制:Dubbo、RPC调用、共享远程数据、消息队列等
消息队列MQ:Kafka、MetaQ,RocketMQ
怎样打造高可用系统:基于硬件、软件中间件、系统架构等一些典型方案的实现:HAProxy、基于Corosync+Pacemaker的高可用集群套件中间件系统
Mycat架构分布式演进
大数据Join背后的难题:数据、网络、内存和计算能力的矛盾和调和
Java分布式系统中的高性能难题:AIO,NIO,Netty还是自己开发框架?
高性能事件派发机制:线程池模型、Disruptor模型等等。。。

合抱之木,生于毫末;九层之台,起于垒土;千里之行,始于足下。不积跬步,无以至千里;不积小流,无以成江河。

Kotlin 简介

Kotlin是一门非研究性的语言,它是一门非常务实的工业级编程语言,它的使命就是帮助程序员们解决实际工程实践中的问题。使用Kotlin 让 Java程序员们的生活变得更好,Java中的那些空指针错误,浪费时间的冗长的样板代码,啰嗦的语法限制等等,在Kotlin中统统消失。Kotlin 简单务实,语法简洁而强大,安全且表达力强,极富生产力。

Java诞生于1995年,至今已有23年历史。当前最新版本是 Java 9。在 JVM 生态不断发展繁荣的过程中,也诞生了Scala、Groovy、Clojure 等兄弟语言。

Kotlin 也正是 JVM 家族中的优秀一员。Kotlin是一种现代语言(版本1.0于2016年2月发布)。它最初的目的是像Scala那样,优化Java语言的缺陷,提供更加简单实用的编程语言特性,并且解决了性能上的问题,比如编译时间。 JetBrains在这些方面做得非常出色。

Kotlin语言的特性

用 Java 开发多年以后,能够尝试一些新的东西真是太棒了。如果您是 Java 开发人员,使用 Kotlin 将会非常自然流畅。如果你是一个Swift开发者,你将会感到似曾相识,比如可空性(Nullability)。 Kotlin语言的特性有:

1.简洁

大幅减少样板代码量。

2.与Java的100%互操作性

Kotlin可以直接与Java类交互,反之亦然。这个特性使得我们可以直接重用我们的代码库,并将其迁移到 Kotlin中。由于Java的互操作性几乎无处不在。我们可以直接访问平台API以及现有的代码库,同时仍然享受和使用 Kotlin 的所有强大的现代语言功能。

3.扩展函数

Kotlin 类似于 C# 和 Gosu, 它提供了为现有类提供新功能扩展的能力,而不必从该类继承或使用任何类型的设计模式 (如装饰器模式)。

4.函数式编程

Kotlin 语言一等支持函数式编程,就像Scala一样。具备高阶函数、Lambda 表达式等函数式基本特性。

5.默认和命名参数

在Kotlin中,您可以为函数中的参数设置一个默认值,并给每个参数一个名称。这有助于编写易读的代码。

6.强大的开发工具支持

And because it is produced by JetBrains, we have great IDE support. Although the automatic conversion from Java to Kotlin is not 100% OK, it is indeed a very good tool. When using IDEA's tools to convert Java code to Kotlin code, 60%-70% of the resulting code can be reused easily, and the cost of modification is small.

In addition to its concise and powerful syntax features, Kotlin also has a very practical API and an ecosystem built around it. For example: collection API, IO extension, reflection API, etc. At the same time, the Kotlin community also provides a wealth of documents and a lot of learning materials, as well as online REPL.

A modern programming language that makes developers happier. Open source forever

Picture from "Kotlin from entry to advanced combat" (Chen Guangjian, Tsinghua University Press)

Picture from "Kotlin from entry to advanced combat" (Chen Guangjian, Tsinghua University Press)

https://kotlinlang.org/

Guess you like

Origin blog.csdn.net/universsky2015/article/details/108669474