Kotlin

历史

2011年7月，JetBrains推出Kotlin项目，这是一个面向JVM的新语言，它已被开发一年之久。JetBrains负责人Dmitry Jemerov说，大多数语言没有他们正在寻找的特性，但是Scala除外。但是，他指出Scala的编译时间过慢这一明显缺陷。Kotlin的既定目标之一是像Java一样快速编译。2012年2月，JetBrains以Apache 2许可证开源此项目。
Jetbrains希望这个新语言能够推动IntelliJ IDEA的销售。
Kotlin v1.0于2016年2月15日发布。这被认为是第一个官方稳定版本，并且JetBrains已准备从该版本开始的长期向后兼容性。
在Google I/O 2017中，Google宣布在Android上为Kotlin提供最佳支持。

语法

Kotlin很明显受到Java、C#、JavaScript、Scala、Groovy等语言的影响。例如Kotlin可以直接通过println("Hello, {name}")或println("Hello, $name")来使用字符串模板，和古老的shell script类似。又如Kotlin中的分号是可选的，这类似JavaScript，而且Groovy、Scala也有同样的能力。Kotlin常量定义关键字是val（不同于变量定义关键字var），表示固定值，这功能来自Scala，Swift也有类似功能。
需要注意，Kotlin没有关键字new。

常量与变量

使用val（全称为value，即（固定的）值）关键字定义常量，定义后其值无法修改
val a: Int = 1 // 定義a為`Int`類型的變量，其值為1val b = 2 // 自動檢測b為`Int`類型
使用var（全称为variable，即变量）关键字定义变量。
var x = 5 // App 定義一個`Int`，值為5x = 1 // 修改值為1

函数

使用fun关键字定义一个函数。
fun sum(a: Int, b: Int): Int {
    return a + b}
上例定义了一个传入两个Int变量，并返回两数之和的求和函数。

Main 进入点

Kotlin的main函数是不依赖类别的，所以main函数是一个top-level函数。支持Perl和Unix/Linux shell script的字符串插值（String interpolation），同样也支持类型推定。
1 // Hello, world! 範例2 fun main(args: Array<String>) {3   val scope = "world"4   println("Hello, $scope!")5 }

函数扩展

Kotlin与C#、JavaScript类似，能够扩展类别的新功能，而无需继承该类别，或使用像装饰器（decorator）这样的任何类型的设计模式（design pattern）。扩展函数可以称为Kotlin的核心，在标准库里到处充斥着扩展函数。
扩展函数是静态分发的，也就是说，它们不是以接收者类型为准的虚拟函数。这意味着调用的扩展函数是由函数调用所在的表达式的类型来决定的，而不是由表达式运行时求值结果决定的。
在下述例子中，String类别被扩展出一个成员lastChar。
1     package MyStringExtensions2 3     fun String.lastChar(): Char = get(length - 1)4 5     >>> println("Kotlin".lastChar())
利用函数扩展，Kotlin也支持运算符重载：
1     // overloading '+' operator using an extension method2     operator fun Point.plus(other: Point): Point {3         return Point(x + other.x, y + other.y)4     }5 6     >>> val p1 = Point(10, 20)7     >>> val p2 = Point(30, 40)8     >>> println(p1 + p2)9     Point(x=40, y=60)

getter和setter

Kotlin像C#一样支持属性（property）。

解包引数

类似Python, 解包（unpack）指的是对实际参数的解包，只需在前面加一个星号* 即可，如test（*a）:
1     fun main(args: Array<String>) { 
2         val list = listOf("args: ", *args)3         println(list)4     }

函数嵌套

Kotlin支持函数嵌套（nested functions），允许函数内再定义函数，类似JavaScript、C#与Python语言。
 1     class User( 2         val id:      Int, 
 3         val name:    String, 
 4         val address: String) 
 5     { 
 6  7         fun saveUser(user: User) { 8            fun validate(user: User, value: String, fieldName: String) { 9                if (value.isEmpty()) {10                    throw IllegalArgumentException(11                       "Can't save user ${user.id}: empty $fieldName")12                }13            }14 15            validate(user, user.name, "Name") 
16            validate(user, user.address, "Address")17            // Save user to the database18         }19     }

解构声明

Kotlin支持解构声明，这与Python的迭代解包相似。
例如, collection object 包含析构式可分离其元素:
1     for ((index, element) in collection.withIndex()) { 
2          println("$index: $element")3     }

抽象类别

抽象类别（Abstract classes）定义抽象或纯虚拟（Pure Virtual）占位函数，需要被继承。抽象类别默认是open的。

    
 1     // No need for the open keyword here, its already open by default 2     abstract class Animated { 3  4         // This virtual function is already open by default as well 5         abstract fun animate() 6   
 7         open fun stopAnimating() { } 8  9         fun animateTwice() { }10     }

主构造函数vs. 二级构造函数

在Kotlin 中类别可以有一个主构造函数以及多个二级构造函数。如果主构造函数没有注解或可见性说明，则constructor关键字可以省略。如果构造函数中没有其它操作，大括号也可以省略。

    
1      // Example of class using primary constructor syntax2      // (Only one constructor required for this class)3      class User(4          val nickname: String, 
5          val isSubscribed: Boolean = true) 
6      {7          ...8      }
Kotlin 的二级构造函数更类似于C++, C#, 和 Java。

    
 1     // Example of class using secondary constructor syntax 2     // (more than one constructor required for this class) 3     class MyButton : View { 4  5         // Constructor #1  6         constructor(ctx: Context) : super(ctx) { 
 7             // ...  8         } 
 9   
10         // Constructor #211         constructor(ctx: Context, attr: AttributeSet) : super(ctx, attr) { 
12             // ... 13         }14     }

Anko library

Anko 是一组为Kotlin 打造的函数库，其功能是用来开发Android UI 应用程序。

    
1         fun Activity.showAreYouSureAlert(process: () -> Unit) {2             alert(3               title   = "Are you sure?",4               message = "Are you really sure?") 
5             {6               positiveButton("Yes") { process() }7               negativeButton("No") { cancel() }8             }9         }

Kotlin 交互模式

Kotlin除了编译成Java字节码运行，也可以作为脚本语言解释运行，此特性使得Kotlin可以以交互模式运行。交互模式是脚本语言具有的特性，解释器可以立即运行用户输入的代码，并反馈运行结果。典型的语言有Python、JavaScript（在V8引擎支持下）、Ruby。
$ kotlinc-jvm
type :help for help; :quit for quit
>>> 2+2
4
>>> println("Welcome to the Kotlin Shell")
Welcome to the Kotlin Shell
>>>

Kotlin 也是脚本语言

Kotlin 亦可视为脚本语言（scripting language）。其脚本存成Kotlin source file (.kts)，即成为可执行档。
1 // list_folders.kts2 import java.io.File3 val folders = File(args[0]).listFiles { file -> file.isDirectory() }4 folders?.forEach { folder -> println(folder) }
为了运行Kotlin 脚本，我们在运行编译器时再加上-script选项。
1 $ kotlinc -script list_folders.kts "path_to_folder_to_inspect"

Kotlin 的 hello world 例子

1 fun main(args: Array<String>) { 2     
 3     greet { 4         to.place 5     }.print() 6 } 7  8 //inline higher-order functions 9 inline fun greet(s: () -> String) : String = greeting andAnother s()  
10 11 //infix functions, extensions, type inference, nullable types, lambda expressions, labeled this, elvis operator12 infix fun String.andAnother(other : Any?) = buildString() { append(this@andAnother); append(" "); append(other ?: "") } 
13 14 //immutable types, delegated properties, lazy initialization, string templates15 val greeting by lazy { val doubleEl: String = "ll"; "he${doubleEl}o" }16 17 //sealed classes, companion objects18 sealed class to { companion object { val place = "world"} }19 20 //extensions, Unit21 fun String.print() = println(this)

高阶函数与lambda

Kotlin 亦支持高阶函数和lambdas功能。lambda是一种匿名函数，允许开发者直接将表达式定义为函数，这类似于Python。
  // the following function takes a lambda, f, and executes f passing it the string, "lambda"
  // note that (s: String) -> Unit indicates a lambda with a String parameter and Unit return type
  fun executeLambda(f: (s: String) -> Unit) {
    f("lambda")
  }
Lambdas 可用大括弧{  } 来定义。如果lambda 夹带参数，他们可定义在大括弧内，并以->运算符区隔。
  // the following statement defines a lambda that takes a single parameter and passes it to the println function
  val l = { c : Any? -> println(c) }
  // lambdas with no parameters may simply be defined using { }
  val l2 = { print("no parameters") }