最近在學習 Kotlin 將官方出的練習題做了一遍,將答案以及做題的時候的一些思考記錄於此:
開始
執行:git clone [email protected]:Kotlin/kotlin-koans.git
,使用 Idea 打開項目。
1 轉換Java代碼
fun task1(collection: Collection<Int>): String {
val sb = StringBuilder()
sb.append("{")
val iterator = collection.iterator()
while (iterator.hasNext()) {
val element = iterator.next()
sb.append(element)
if (iterator.hasNext()) {
sb.append(", ")
}
}
sb.append("}")
return sb.toString()
}
2 命名參數
fun task2(collection: Collection<Int>): String {
return collection.joinToString(prefix = "{",postfix = "}")
}
如果之前你瞭解過 Python,很容易理解這一點。在 Kotlin 中,我們可以爲爲參數設置默認值來避免書寫大量重載方法,在使用時,我們可以根據自己的需要按照 參數名 = 參數
這樣的方式填寫需要的參數,使用命名參數時可以忽略參數順序。如果參數中包含沒有使用命名的參數,那這些參數任然遵循方法簽名的順序。
3 默認參數
fun foo(name: String, number: Int = 42, toUpperCase: Boolean = false): String = (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))
}
4 Lambda 表達式
fun task4(collection: Collection<Int>): Boolean {
return collection.filter {
it%2==0
}.isEmpty().not()
}
過濾函數: filter{(T) -> Boolean}
根據傳入的判斷函數返回一個新的 List 集合
5 字符串模板
fun task5(): String = """\d{2} ${month} \d{4}"""
在 kotlin 中,我們可以在字符串中使用 ${}
來包含一個變量或是一個表達式,如果只是一個變量的情況,可以省略花括號。
6 數據類
data class Person(var name:String,var age :Int)
fun task6(): List<Person> {
return listOf(Person("Alice", 29), Person("Bob", 31))
}
7 可空類型
要知道 Kotlin 最大的特點就是空安全,除非我們主動生命,不然所有的對象都是不可爲空的。申明一個可空類型的方法十分簡單,只需要在類型聲明後面加上 ?
fun sendMessageToClient(client: Client?, message: String?, mailer: Mailer) {
client?.personalInfo?.email?.let {email->
message?.let {
mailer.sendMessage(email,it)
}
}
}
class Client (val personalInfo: PersonalInfo?)
class PersonalInfo (val email: String?)
interface Mailer {
fun sendMessage(email: String, message: String)
}
使用 ?.let{}
可以讓我們安全的調用可空類型
8 智能轉型
fun eval(e: Expr): Int =
when (e) {
is Num -> {
e.value
}
is Sum -> {
eval( e.left)+ eval(e.right)
}
}
when 表達式可以幫助我們智能轉型,當傳入的對象在通過 is xxx 判斷之後,將自動的轉型成這個類型,我們可以直接使用,而無需在顯示轉型。
9 擴展函數
fun Int.r(): RationalNumber = RationalNumber(this,1)
fun Pair<Int, Int>.r(): RationalNumber = RationalNumber(first,second)
擴展函數的聲明與使用都非常簡單,使用 fun 類名.函數名(參數...):返回值
的方式即可聲明一個擴展函數,調用也十分方便,就像調用這個類的自有函數一樣自然。
10 object 表達式
fun task10(): List<Int> {
val arrayList = arrayListOf(1, 5, 2)
Collections.sort(arrayList, object :Comparator<Int>{
override fun compare(o1: Int, o2: Int): Int {
return o2-o1
}
})
return arrayList
}
在 Java 中我們通常使用 new XXXInterface(){}
來創建一個接口或是抽象類的匿名內部類,但是在 Kotlin 中沒有 new
這個關鍵字,我們可以使用 object 關鍵字來創建一個接口或是抽象類的實現對象。當然,通常的,面對這種僅有一個方法需要實現的接口,我們完全可以使用 Lambda 表達式來書寫,這樣代碼更加簡潔。
11 SAM 轉換
fun task11(): List<Int> {
val arrayList = arrayListOf(1, 5, 2)
Collections.sort(arrayList, { x, y -> y-x })
return arrayList
}
當一個對象需要實現了一個 SAM(單一抽象方法)接口,你可以使用 Lambda 表達式來代替他。另外,如果一個方法的最後一個參數是一個 SAM 接口,我們可以將 {}
包裹的 Lambda 表達式放到括號外面,效果如下:
Collections.sort(arrayList) { x, y -> y-x }
12 集合擴展
fun task12(): List<Int> {
return arrayListOf(1, 5, 2).sortedDescending()
}
對 List 降序排列,在 kotlin 中只需要調用它的擴展方法即可!