Kotlin

維基百科,自由的百科全書
跳至導覽 跳至搜尋
Kotlin
Kotlin 圖示
編程範型多範式物件導向函數式指令式宣告式泛型反射式並行
設計者JetBrains
實作者JetBrains與開源貢獻者
釋出時間2011
目前版本
    Module:EditAtWikidata第29行Lua錯誤:attempt to index field 'wikibase' (a nil value)
    型態系統靜態類型類型推論
    系統平台輸出Java虛擬機Java位元組碼以及JavaScript原始碼
    作業系統任何支援JVM或是JavaScript的直譯器
    許可證Apache 2
    副檔名.kt .kts
    網站{{URL|example.com|可选的显示文本}}Module:EditAtWikidata第29行Lua錯誤:attempt to index field 'wikibase' (a nil value)
    受影響於
    JavaScalaGroovyC#Gosu英語Gosu

    Kotlin是一種在Java虛擬機上執行的靜態型別程式語言,它也可以被編譯成為JavaScript原始碼。

    歷史[編輯]

    2011年7月,JetBrains俄羅斯聖彼得堡的開發團隊推出Kotlin專案,其名稱來自於聖彼得堡附近的科特林島[1]2012年1月,著名期刊《Dr. Dobb's Journal英語Dr. Dobb's Journal》中Kotlin被認定為該月的最佳語言。[2]。這是一個面向JVM的新語言,它已被開發一年之久。[3]JetBrains負責人Dmitry Jemerov說,大多數語言沒有他們正在尋找的特性,但是Scala除外。但是,他指出Scala的編譯時間過長這一明顯缺陷。[3]Kotlin的既定目標之一是像Java一樣快速編譯。2012年2月,JetBrains以Apache 2許可證開源此專案。[4]

    JetBrains希望這個新語言能夠推動IntelliJ IDEA的銷售。[5]

    雖然與Java語法並不相容,但在JVM環境中Kotlin被設計成可以和Java程式碼相互運作,並可以重複使用如Java集合框架等的現有Java參照的函式庫英語Java Class Library。Hathibelagal寫道,「如果你正在為Android開發尋找一種替代程式語言,那麼應該試下Kotlin。它很容易在Android專案中替代Java或者同Java一起使用。」

    Kotlin v1.0於2016年2月15日發佈。[6]這被認為是第一個官方穩定版本,並且JetBrains已準備從該版本開始的長期向下相容性。

    Google I/O 2017中,Google宣佈在Android上為Kotlin提供最佳支援。[7]

    語法[編輯]

    Kotlin很明顯受到JavaC#JavaScriptScalaGroovy等語言的影響。例如Kotlin可以直接通過println("Hello, ${name}")println("Hello, $name")來使用字串模板,和古老的shell script類似。又如Kotlin中的分號是可選的,這類似JavaScript,而且Groovy、Scala也有同樣的能力。Kotlin常數定義關鍵字是val(不同於變量定義關鍵字var),表示固定值,這功能來自Scala,Swift也有類似功能。

    需要注意,Kotlin沒有關鍵字new

    變量[編輯]

    使用val(全稱為value,即(固定的)值)關鍵字定義唯讀變量,定義後其值無法修改[8]

    val a: Int = 1 // 定義a為`Int`類型的唯讀變量,其值為1
    val b = 2 // 自動檢測b為`Int`類型
    

    使用var(全稱為variable,即變量)關鍵字定義可變變量。

    var x = 5 // App 定義一個`Int`,值為5
    x = 1 // 修改值為1
    

    函數[編輯]

    使用fun關鍵字定義一個函數。

    fun sum(a: Int, b: Int): Int {
        return a + b
    }
    

    上例定義了一個傳入兩個Int變量,並返回兩數之和的求和函數。

    程式的入口點[編輯]

    類似於 C、 C++、 C#、 Java 和 Go , Kotlin 程式的入口點是一個名為「main」的函數。 main 函數有一個包含命令列選項的參數(從 Kotlin 1.3 開始是可選的)。 Kotlin 支援像 PerlUnix shell 那樣的字串模板英語String interpolation類型推斷也是支援的。

    // Hello, world! 範例
    fun main() {
        val scope = "World"
        println("Hello, $scope!")
    }
    
    fun main(args: Array<String>) {
        for (arg in args) {
            println(arg)
        }
    }
    

    函數擴充[編輯]

    Kotlin與C#、JavaScript類似,能夠擴充類別的新功能,而無需繼承該類別,或使用像裝飾器(decorator)這樣的任何類型的設計模式(design pattern)。擴充函數可以稱為Kotlin的核心,在標準庫里到處充斥着擴充函數。

    擴充函數是靜態分發的,也就是說,它們不是以接收者類型為準的虛擬函數。這意味着呼叫的擴充函數是由函數呼叫所在的表達式的類型來決定的,而不是由表達式執行時求值結果決定的。

    在下述例子中,String類別被擴充出一個成員lastChar。

    package MyStringExtensions
    
    fun String.lastChar(): Char = get(length - 1)
    
    >>> println("Kotlin".lastChar())
    

    利用函數擴充,Kotlin也支援運算子多載

    // overloading '+' operator using an extension method
    operator fun Point.plus(other: Point): Point {
        return Point(x + other.x, y + other.y)
    }
    
    >>> val p1 = Point(10, 20)
    >>> val p2 = Point(30, 40)
    >>> println(p1 + p2)
    Point(x=40, y=60)
    

    getter和setter[編輯]

    Kotlin像C#一樣支援屬性(property)。

    解包引數[編輯]

    類似Python, 解包(unpack)指的是對實際參數的解包,只需在前面加一個星號* 即可,如test(*a):

    fun main(args: Array<String>) { 
        val list = listOf("args: ", *args)
        println(list)
    }
    

    函數巢狀[編輯]

    Kotlin支援函數巢狀(nested functions),允許函數內再定義函數,類似JavaScript、C#與Python語言。

    class User(
        val id:      Int, 
        val name:    String, 
        val address: String) { 
    
        fun saveUser(user: User) {
           fun validate(user: User, value: String, fieldName: String) {
               if (value.isBlank()) {
                   throw IllegalArgumentException(
                      "Can't save user ${user.id}: empty $fieldName")
               }
           }
    
           validate(user, user.name, "Name") 
           validate(user, user.address, "Address")
           // Save user to the database
        }
    }
    

    解構聲明[編輯]

    Kotlin支援解構聲明,這與Python的迭代解包相似。

    例如, collection object 包含解構式可分離其元素:

    for ((index, element) in collection.withIndex()) { 
         println("$index: $element")
    }
    

    抽象類別[編輯]

    抽象類別(Abstract classes)定義抽象或純虛擬(Pure Virtual)佔位函數,需要被繼承。抽象類別預設是open的。

    // No need for the open keyword here, its already open by default
    abstract class Animated {
    
        // This virtual function is already open by default as well
        abstract fun animate()
    
        open fun stopAnimating() { }
    
        fun animateTwice() { }
    }
    

    類別屬性[編輯]

    Kotlin 提供下列的關鍵字來限制頂層(top-level)聲明,用於控制類別與成員在繼承時的可見性(範疇)。它們可用於類別及其成員:

    public
    internal
    protected
    private
    

    用於類別的成員聲明時,含義如下:

    • public:全域可見。此為預設的類型。
    • internal:在當前模組中可見。
    • protected:在當前類別的一級子類別中可見,如果子類別再被繼承,則在下一級子類別中不可見。
    • private:在當前類別中可見。

    用於頂層聲明時,含義如下:

    • public:全域可見。此為預設的類型。
    • internal:在當前模組中可見。
    • private:在當前檔案中可見。

    例如:

    // Class is visible only to current module
    internal open class TalkativeButton : Focusable {
        // method is only visible to current class 
        private   fun yell() = println("Hey!") 
    
        // method is visible to current class and derived classes
        protected fun whisper() = println("Let's talk!")
    }
    

    主建構函式 vs. 二級建構函式[編輯]

    在Kotlin 中類別可以有一個主建構函式以及多個二級建構函式。如果主建構函式沒有註解或可見性說明,則constructor關鍵字可以省略。如果建構函式中沒有其它操作,大括號也可以省略。

    // Example of class using primary constructor syntax
    // (Only one constructor required for this class)
    class User(
        val nickname: String, 
        val isSubscribed: Boolean = true) {
        ...
    }
    

    Kotlin 的二級建構函式更類似於 C++, C#, 和 Java。

    // Example of class using secondary constructor syntax
    // (more than one constructor required for this class)
    class MyButton : View {
    
        // Constructor #1 
        constructor(ctx: Context) : super(ctx) { 
            // ... 
        } 
    
        // Constructor #2
        constructor(ctx: Context, attr: AttributeSet) : super(ctx, attr) { 
            // ... 
        }
    }
    

    Anko library[編輯]

    Anko 是一組為Kotlin 打造的函式庫,其功能是用來開發Android UI 應用程式,[9]隨着同類功能的Jetpack Compose英語Jetpack Compose發展,Anko現已棄用。[10]

    fun Activity.showAreYouSureAlert(process: () -> Unit) {
        alert(
          title   = "Are you sure?",
          message = "Are you really sure?") 
        {
          positiveButton("Yes") { process() }
          negativeButton("No") { cancel() }
        }
    }
    

    Kotlin 互動模式[編輯]

    Kotlin除了編譯Java位元組碼執行,也可以作為手稿語言解釋執行,此特性使得Kotlin可以以互動模式執行。互動模式是手稿語言具有的特性,直譯器可以立即執行用戶輸入的代碼,並反饋執行結果。典型的語言有PythonJavaScript(在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),即成為可執行檔。

    // list_folders.kts
    import java.io.File
    val folders = File(args[0]).listFiles { file -> file.isDirectory() }
    folders?.forEach { folder -> println(folder) }
    

    為了執行Kotlin 指令碼,我們在執行編譯器時再加上-script選項。

    $ kotlinc -script list_folders.kts "path_to_folder_to_inspect"
    

    Kotlin 的 hello world 例子[編輯]

    fun main(args: Array<String>) {
        
        greet {
            to.place
        }.print()
    }
    
    //inline higher-order functions
    inline fun greet(s: () -> String) : String = greeting andAnother s()  
    
    //infix functions, extensions, type inference, nullable types, lambda expressions, labeled this, elvis operator
    infix fun String.andAnother(other : Any?) = buildString() { append(this@andAnother); append(" "); append(other ?: "") } 
    
    //immutable types, delegated properties, lazy initialization, string templates
    val greeting by lazy { val doubleEl: String = "ll"; "he${doubleEl}o" }
    
    //sealed classes, companion objects
    sealed class to { companion object { val place = "world"} }
    
    //extensions, Unit
    fun String.print() = println(this)
    

    空變量及其運算[編輯]

    Kotlin對可以為空(nullable)的變量和不可以為空(non-nullable)的變量作了區分。所有的可空對象(nullable objects)必須在定義時加上 "?" 後置於類型之後。開發人員遇到nullable objects時要先確認: null-check 須被執行過,才能賦值。可空性是Kotlin型別系統中幫助開發者避免以往Java的NullPointerException錯誤的特性。

    Kotlin 提供空安全(null-safe)運算子給開發人員:

    fun sayHello(maybe: String?, neverNull: Int) {
       // use of elvis operator
       val name: String = maybe ?: "stranger"
       println("Hello $name")
    }
    

    使用安全導引(safe navigation)運算子:

    // returns null if...
    // - foo() returns null,
    // - or if foo() is non-null, but bar() returns null,
    // - or if foo() and bar() are non-null, but baz() returns null.
    // vice versa, return value is non-null if and only if foo(), bar() and baz() are non-null
    foo()?.bar()?.baz()
    

    高階函數與lambda[編輯]

    Kotlin 亦支援高階函數和lambdas功能。lambda是一種匿名函數,允許開發者直接將表達式定義為函數,這類似於Python。[11]

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

    參考資料[編輯]

    1. ^ Heiss, Janice. The Advent of Kotlin: A Conversation with JetBrains' Andrey Breslav. oracle.com. Oracle Technology Network. April 2013 [February 2, 2014]. (原始內容存檔於2017-05-08). 
    2. ^ Breslav, Andrey. Language of the Month: Kotlin. drdobbs.com. January 20, 2012 [February 2, 2014]. (原始內容存檔於2015-10-22). 
    3. ^ 3.0 3.1 Krill, Paul. JetBrains readies JVM language Kotlin. infoworld.com. InfoWorld. Jul 22, 2011 [February 2, 2014]. (原始內容存檔於2014-07-15). 
    4. ^ Waters, John. Kotlin Goes Open Source. ADTmag.com/. 1105 Enterprise Computing Group. February 22, 2012 [February 2, 2014]. (原始內容存檔於2016-03-29). 
    5. ^ Why JetBrains needs Kotlin. [2017-05-18]. (原始內容存檔於2014-04-21). we expect Kotlin to drive the sales of IntelliJ IDEA 
    6. ^ Kotlin 1.0 Released: Pragmatic Language for JVM and Android | Kotlin Blog. Blog.jetbrains.com. 2016-02-15 [2017-04-11]. (原始內容存檔於2016-10-22). 
    7. ^ Shafirov, Maxim. Kotlin on Android. Now official. May 17, 2017 [2017-05-18]. (原始內容存檔於2021-01-31). Today, at the Google I/O keynote, the Android team announced first-class support for Kotlin. 
    8. ^ Basic Syntax. Kotlin. Jetbrains. [19 January 2018]. (原始內容存檔於2021-01-29). 
    9. ^ Anko Github. [2018-06-02]. (原始內容存檔於2020-12-13). 
    10. ^ anko/GOODBYE.md. [2020-03-11]. (原始內容存檔於2022-04-28). 
    11. ^ Higher-Order Functions and Lambdas. Kotlin. Jetbrains. [19 January 2018]. (原始內容存檔於2021-01-22). 

    外部連結[編輯]