用Kotlin-koans學Kotlin【二】i_introduction

HankeXu發表於2017-10-15

這一節名為 “i_introduction(介紹)”,主要向我們展示了Kotlin的語法,特性,與JAVA的相似與不同。

在使用Kotlin-koans學習時,我們的練習都在src目錄下,開啟後可以看到我們的練習,我們要做的就是根據提示完成練習,並執行test目錄下對應的單元測試,如果單元測試報錯,說明沒有通過,若什麼都沒輸出,則說明完成了練習。

0. _0_Hello_World

先貼一下程式碼

package i_introduction._0_Hello_World

import util.TODO
import util.doc0

fun todoTask0(): Nothing = TODO(
    """
        Task 0.

        Read README.md to learn how to work with this project and check your solutions.

        Using 'documentation =' below the task description you can open the related part of the online documentation.
            Press 'Ctrl+Q'(Windows) or 'F1'(Mac OS) on 'doc0()' to call the "Quick Documentation" action;
            "See also" section gives you a link.
            You can see the shortcut for the "Quick Documentation" action used in your IntelliJ IDEA
            by choosing "Help -> Find Action..." (in the top menu), and typing the action name ("Quick Documentation").
            The shortcut in use will be written next to the action name.

        Using 'references =' you can navigate to the code mentioned in the task description.

        Let's start! Make the function 'task0' return "OK". Note that you can return expression directly.
    """,
    documentation = doc0(),
    references = { task0(); "OK" }
)

fun task0(): String {
    return todoTask0()
}複製程式碼

閱讀TODO中的內容,首先要求我們閱讀README.md檔案,學習如何使用該專案,瞭解通過該專案能學到什麼,並給出了Hello_World練習的答案。然後是教我們使用線上文件,可以看到程式碼中有一個doc0()函式,將游標移動到該函式位置,按下 'Ctrl + Q'(Mac OS按 'F1')可以開啟快速文件,這裡是Kotlin的詳細文件,點選連結便可在瀏覽器中檢視。注意一定要將游標移動到該函式位置,只是將滑鼠懸停在函式上方是不行的。

接下來就是本練習的內容了,修改task0()函式使其返回一個"OK"

fun task0(): String {
    return todoTask0()
}複製程式碼

練習中所有todo字首的函式都是為了說明練習內容和不讓編輯器報錯的,我們修改時不需要改動它們,不要呼叫就可以了。
開始練習

fun task0(): String {
    return "OK"
}複製程式碼

完成,也可以這樣,省略函式體,直接給函式賦值

fun task0(): String = "OK"複製程式碼

還可以這樣,連返回值型別都省略

fun task0() = "OK"複製程式碼

然後開啟test目錄,找到對應的單元測試,執行


不出意外我們將看到如下結果


這就說明我們用Kotlin說出了Hello World,馬不停蹄地開始下一個專案吧。

1. _1_Java_To_Kotlin_Converter

該練習教我們使用把Java程式碼轉為Kotlin程式碼的工具,Intellj IDEA 自帶了這個工具,我們將JavaCode1.java中的task1方法複製到n01JavaToKotlinConverter.kt中,直接覆蓋對應的task1函式就好了

  • 選擇 => 複製
  • 貼上 => Yes
  • 轉換就完成了

執行測試,通過

2. _2_Named_Arguments

Kotlin中,我們在呼叫方法或函式的時候,可以使用方法或函式中形參的名字傳參,也可以為形參設定預設值

fun bar(i: Int, s: String = "", b: Boolean = true) {}複製程式碼

可以看到函式bar()中有三個形參i,s,b,sb都設定了預設值,所以呼叫的時候必須傳遞的引數就只有i

bar(1)複製程式碼

因為可以使用形參的名字傳參,我們在呼叫函式的時候就不用關心引數的順序了

bar(1, b = fasle)複製程式碼

好方便
練習要求我們使用庫函式joinToString設定前字尾{},我們使用形參名傳值

fun task2(collection: Collection<Int>): String {
    return collection.joinToString(postfix = "}",prefix = "{")
}複製程式碼

完成,引數順序打亂都沒問題

3. _3_Default_Arguments

使用引數預設值,修改foo函式,實現Java中需要過載才能實現的功能

fun foo(name: String, number: Number = 42, toUpperCase: Boolean = false): String {
    return (if (toUpperCase) name.toUpperCase() else name) + number
}

fun task3(): String {
    return (foo("a") +
            foo("b", number = 1) +
            foo("c", toUpperCase = true) +
            foo(name = "d", number = 2, toUpperCase = true))
}複製程式碼

完成,太方便了。
這裡我們注意到,Kotlin中的if語句可以直接返回結果,不需要寫return語句,而我們熟悉的三目運算子 ?:Kotlin中另有它用。

4. _4_Lambdas

使用lambda表示式,遍歷集合,不能使用Iterables,包含偶數返回ture,反之false

fun task4(collection: Collection<Int>): Boolean = collection.any { x -> x % 2 == 0 }複製程式碼

呼叫Collectionany方法,並完成表示式即可,any表示集合中有任一元素符合表示式,結果即為true,我關於Lambda表示式的內容瞭解很少,還要專門學習。

5. _5_String_Templates

字串模板
"Any expression can be used: ${if (c) x else y}" ,使用${}可在字串中使用變數或表示式,用"""String""",字串中不需要用\來轉義,可以直接使用各種符號,包括換行符
修改模板字串,使其可以匹配測試中的日期格式

fun task5(): String ="""\d{2}\ ${month}\ \d{4}"""複製程式碼

6. _6_Data_Classes

資料類,Kotlin中專門用來構造資料實體類的方式,非常簡潔
補全Person
data class Person(val name: String, val age: Int)

7. _7_Nullable_Types

可空型別,練習要求我們重構JavaCode7.java中的sendMessageToClient方法,但是隻能使用一次if 語句,用Kotlin當然是可以做到的

fun sendMessageToClient(client: Client?, message: String?, mailer: Mailer) {
    if (client == null || message == null) return

    val personalInfo = client.personalInfo ?: return

    val email = personalInfo.email ?: return

    mailer.sendMessage(email, message)
}複製程式碼

函式簽名中的跟在型別後邊的?表示可傳入空值,而在函式體中我們看到了已經不是原來的?:?:,這裡的?:稱為elvis操作符,它的功能是判斷變數或表示式的值是否為空,非空返回操作符左邊,空則返回右邊,?:是一個整體,不可在中間加入其他東西。

8. _8_Smart_Casts

使用智慧轉換和when表示式完成eval方法,實現和JavaCode8.java中同樣的功能

fun eval(e: Expr): Int =
        when (e) {
            is Num -> e.value
            is Sum -> eval(e.left) + eval(e.right)
            else -> throw IllegalArgumentException("Unknown expression")
        }複製程式碼

Kotlin中沒有switch表示式,但是when提供了更豐富的功能,在when中,我們使用->表示執行某一分支後的操作,->之前是條件,條件不一定是某個值,它可以是任意表示式。
多個條件執行同一操作,可用,分隔

when (x) {
    0, 1 -> print("x == 0 or x == 1")
    else -> print("otherwise")
}複製程式碼

可以用in!in選擇在或不在某一範圍

when (x) {
    in 1..10 -> print("x is in the range")
    in validNumbers -> print("x is valid")
    !in 10..20 -> print("x is outside the range")
    else -> print("none of the above")
}複製程式碼

可以用is智慧轉換型別,如同本練習
when沒有引數的時候,也可以用來替代if-else if

when {
    x.isOdd() -> print("x is odd")
    x.isEven() -> print("x is even")
    else -> print("x is funny")
}複製程式碼

還有,當編譯器認為我們提供的條件分支沒有覆蓋所以情況時,我們必須使用else,它相當於switch中的default

9. _9_Extension_Functions

Kotlin支援為已經存在的類編寫擴充套件方法,而且不需要對原有類進行任何改動,只需要使用className.extensionFun的形式就可以了

fun String.lastChar() = this.get(this.length - 1)複製程式碼

本練習要求我們使用擴充套件方法為IntPair擴充套件r方法,r方法的功能是構造一個RationalNumber類的物件

fun Int.r(): RationalNumber = RationalNumber(this,1)
fun Pair<Int, Int>.r(): RationalNumber = RationalNumber(first,second)複製程式碼

簡單靈活,非常強大

10. _10_Object_Expressions

JAVA中我們要實現一個介面或使用一個抽象類時通常會使用匿名內部類,在Kotlin中,我們使用Object Expressions【物件表示式】,看上去這和在Java中沒有太大不同
本練習中我們使用物件表示式來實現Collections.sort中的Comparator

fun task10(): List<Int> {
    val arrayList = arrayListOf(1, 5, 2)
    Collections.sort(arrayList, object : Comparator<Int> {
        override fun compare(o1: Int, o2: Int): Int = o2 - o1
    })
    return arrayList
}複製程式碼

11. _11_SAM_Conversions

Kotlin支援SAM轉換,我沒弄懂這是什麼原理,總之很神奇。使用這個功能,我們可以進一步簡化上一練習中的方法

fun task11(): List<Int> {
    val arrayList = arrayListOf(1, 5, 2)
    Collections.sort(arrayList, { x, y -> y-x })
    return arrayList
}複製程式碼

12. _12_Extensions_On_Collections

Kotlin的標準庫提供為Collections提供了非常多有用的擴充套件方法,如上一練習當中的從大到小排序,方法名為sortedDescending,呼叫此方法就可方便地完成排序了

fun task12(): List<Int> {
    return arrayListOf(1, 5, 2).sortedDescending()
}複製程式碼

相關文章