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