Kotlin Primer·第二章·基本語法 原 薦

題外話:全書的目錄以及主要內容已經公開,可在我公衆號【技術實驗室】的歷史推送文章查看

已經公開章節:
第一部分——快速上手
第一章·啓程
第二章·基本語法
第三章·Kotlin 與 Java 混編
第二部分——開始學習 Kotlin
第四章·類與對象(上)

Kotlin 程序是什麼樣子的?如果瀏覽過本書,你會看到許多例子。很有可能你覺得 Kotlin 語言有點古怪,充滿了var field: String這樣的語法。然而讀完本章後,你將不再對這些語法感到陌生,甚至很可能喜歡上它們。

2.1 變量

讓我們來看一個很簡單的程序。

fun main(args: Array<String>) {
    var quantity = 5
    val price: Double = 20.3
    val name: String = "大米"

    println("單價:$price")
    println("數量:$quantity")
    println("產品:$name 總計:${quantity * price}")
}

上面的代碼中,首先創建了一個名爲quantity的變量用以表示產品的數量,並初始化爲 5。
一個值爲 20.3 的常量price,用來表示產品的單價。
一個表示產品名字的字符串常量name

通過這段代碼我們可以看到,Kotlin 語言聲明一個變量使用關鍵字var,聲明一個常量使用val,聲明時 Kotlin 語言是可以自動推測出字段類型的,例如上面代碼中的var quantity = 5會被認爲是Int類型,但如果你希望它是一個Double類型,則需要顯示聲明類型,例如var quantity: Double = 5

2.2 語句

2.2.1 in關鍵字的使用

判斷一個對象是否在某一個區間內,可以使用in關鍵字

//如果存在於區間(1,Y-1),則打印OK
if (x in 1..y-1) 
  print("OK")

//如果x不存在於array中,則輸出Out
if (x !in 0..array.lastIndex) 
  print("Out")

//打印1到5
for (x in 1..5) 
  print(x)

//遍歷集合(類似於Java中的for(String name : names))
for (name in names)
  println(name)

//如果names集合中包含text對象則打印yes
if (text in names)
  print("yes")

2.2.2 when表達式

類似於 Java 中的 switch,但是 Kotlin 更加智能,可以自動判斷參數的類型並轉換爲響應的匹配值。

fun cases(obj: Any) { 
  when (obj) {
    1       -> print("第一項")
    "hello" -> print("這個是字符串hello")
    is Long -> print("這是一個Long類型數據")
    !is String -> print("這不是String類型的數據")
    else    -> print("else類似於Java中的default")
  }
}

2.2.3 智能類型推測

判斷一個對象是否爲一個類的實例,可以使用is關鍵字
與 Java 中的instanceof關鍵字類似,但在 Kotlin 中如果已經確定了一個對象的類型,可以在接下來的代碼塊中直接作爲這個確定類型使用。

fun getStringLength(obj: Any): Int? {
  if (obj is String) {
    // 做過類型判斷以後,obj會被系統自動轉換爲String類型
    return obj.length 
  }

  //同時還可以使用!is,來取反
  if (obj !is String){
  }

  // 代碼塊外部的obj仍然是Any類型的引用
  return null
}

2.2.4 空值檢測

Kotlin 是空指針安全的,也就意味着你不會再看到那惱人的空指針異常。
例如這句代碼 println(files?.size),只會在files不爲空時執行。
以及,你可以這樣寫

//當data不爲空的時候,執行語句塊
data?.let{
	//... 
}

//相反的,以下代碼當data爲空時纔會執行
data?:let{
	//...
}

2.3 函數

2.3.1 函數的聲明

函數使用關鍵字fun聲明,如下代碼創建了一個名爲say()的函數,它接受一個String類型的參數,並返回一個String類型的值

fun say(str: String): String {
	return str
}

同時,在 Kotlin 中,如果像這種簡單的函數,可以簡寫爲

fun say(str: String): String = str

如果是返回Int類型,那麼你甚至連返回類型都可以不寫

fun getIntValue(value: Int) = value

2.3.2 函數的默認參數

你也可以使用默認參數來實現重載類似的功能

fun say(str: String = "hello"): String = str

這時候你可以調用say(),來得到默認的字符串 "hello",也可以自己傳入參數say("world")來得到傳入參數值。

有時參數非常多的時候,也可以使用多行參數的寫法,它們是相同的

fun say(firstName: String = "Tao",
		lastName: String = "Zhang"){
}

2.3.3 變參函數

同 Java 的變長參數一樣,Kotlin 也支持變長參數

//在Java中,我們這麼表示一個變長函數
public boolean hasEmpty(String... strArray){
	for (String str : strArray){
		if ("".equals(str) || str == null)
			return true;
	}
	return false;
}

//在Kotlin中,使用關鍵字vararg來表示
fun hasEmpty(vararg strArray: String?): Boolean{
	for (str in strArray){
		if ("".equals(str) || str == null)
			return true	
	}
	return false
}

2.3.4 擴展函數

你可以給父類添加一個方法,這個方法將可以在所有子類中使用
例如,在 Android 開發中,我們常常使用這樣的擴展函數:

fun Activity.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(this, message, duration).show()
}

這樣,我們就可以在每一個Activity中直接使用toast()函數了。

2.3.5 將函數作爲參數

Kotlin 中,可以將一個函數作爲參數傳遞給另一個函數

fun lock<T>(lock: Lock, body: () -> T ) : T {
	    lock.lock()
	    try {
	        return body()
	    }
	    finally {
	        lock.unlock()
	    }
}

上面的代碼中,我們傳入了一個無參的 body() 作爲 lock() 的參數,

2.4 小結

最後,我們用一段代碼來總結本章內容,你能看懂嗎?

fun main(args: Array<String>) {

    val firstName: String = "Tao"
    val lastName: String? = "Zhang"

    println("my name is ${getName(firstName, lastName)}")
}

fun hasEmpty(vararg strArray: String?): Boolean {
    for (str in strArray) {
        str ?: return true
    }
    return false
}

fun getName(firstName: String?, lastName: String? = "unknow"): String {
    if (hasEmpty(firstName, lastName)) {
        lastName?.let { return@getName "${checkName(firstName)} $lastName" }
        firstName?.let { return@getName "$firstName ${checkName(lastName)}" }
    }
    return "$firstName $lastName"
}

fun checkName(name: String?): String = name ?: "unknow"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章