變數(variable)
- 宣告不可改變的變數
val 變數名稱: 型態 = 初始值
- 宣告可以改變的變數
var 變數名稱: 型態 = 初始值
- 為了讓數值看起來比較清楚,可以自己在需要的地方加上底線。
val v = 1_000_000 // 十進位整數數值使用底線
val v2 = 12_34.56_71_23 // 十進位小數數值使用底線
val v3 = 0b1010_0000_1111_0101 // 二進位整數數值使用底線
- 不同型態的變數在執行數學運算以後,計算的結果預設為Int,如果執行計算的數值或變數型態範圍大於Int的話,計算的結果會是最大的型態
- 若不指定初始值則必須指定變數型態即可
函式(function)
關鍵字:fun
- 宣告方式與swift相同
fun 函式名稱(參數名稱:參數型態,...): 回傳值型態 {
...
return ...
}
沒有回傳值的函式,要把回傳值宣告為
- Unit
- 可省略
可以使用單一運算式函式的宣告語法
fun getHello01(): String = "Hello! Kotlin!"
- 在參數的前面加上「vararg」,可以讓這個參數接收指定型態0到多個資料
// 使用vararg設定參數可以接收零到多個值
// 呼叫這個函式可以在傳遞零到多個整數
// 參數的資料型態為陣列
fun average(vararg ns: Int): Int {
var total = 0
`
// 使用迴圈處理陣列的所有元素(合計)`for (n in ns) {
total += n
}
`
// 傳回平均值`return total / ns.size
}
- 一個函式只能有一個設定為vararg的參數
- 如果除了vararg參數外還有其它參數,vararg參數必須宣告在所有參數的最後一個
字串模板(string template)
- 與swift相同可在字串中加入替換變數的內容
- "...$變數..."
- "...${運算式}..."
- 不建議在Kotlin使用+號連接字串,盡量使用字串模板
條件(conditions)
皆可用於程式判斷或是assign值
if
- 大致上與java相同
- 簡單的if-else運算式寫法
val v: Int = if (x > y) x else y
when
when (grade) {
'A' -> bonus = 5000
'B' -> bonus = 3000
'C' -> bonus = 1000
else -> bonus = 50
}
- 同上,也可使用簡化的運算式語法
val bonus2 =
when (grade) {
'A' -> 5000
'B' -> 3000
'C' -> 1000
else -> 50
}
迴圈(loop)
- for
for (變數名稱 in 起始值..終止值) {
迴圈執行的工作
}
- 顯示: 12345
for (index: Int in 1..5) {
print(index)
}
- 顯示: 135
for (index: Int in 1..5 step 2)
print(index)
- 顯示: 54321
for (index: Int in 5 downTo 1)
print(index)
- 顯示: 12345
- 變化型態
- 從n(最小值)到m(最大值),每次增加x
變數名稱 in <n>..<m> step <x>
- 從n(最小值)到m-1(最大值),每次增加x
變數名稱 in <n> until <m> step <x>
- 從n(最大值)到m(最小值),每次減少x
`
變數名稱 indownTo step `
- 從n(最小值)到m(最大值),每次增加x
- while
- do while
- label
- 應用程式需要使用多層的迴圈執行比較複雜的工作,通常會稱為巢狀迴圈。如果在巢狀迴圈需要執行特別的流程控制,可以先使用標籤(Label)幫迴圈命名,再使用下面的語法:
outer@ for (x in 1..5) {
for (y in 1..5) {
println("X:$x - Y:$y")
`
if (y == 3) {`break@outer
}
}
}
- 應用程式需要使用多層的迴圈執行比較複雜的工作,通常會稱為巢狀迴圈。如果在巢狀迴圈需要執行特別的流程控制,可以先使用標籤(Label)幫迴圈命名,再使用下面的語法:
陣列(array)
- 宣告陣列的方式
val <name>: xxxArray = xxxArray(<元素個數>)
// 可以省略型態的設定
val <name> = xxxArray(<元素個數>)
- 陣列的類別及預設值
- ByteArray、ShortArray、IntArray:0
- LongArray:0L
- FloatArray:0.0F
- DoubleArray:0.0
- CharArray:編碼為0的字元
- BooleanArray:false
- 處理陣列元素的時候,如果需要使用元素的編號,可以使用下面的for迴圈語法
// ages.indices傳回0..2
for (i in ages.indices) {
println("[$i]: ${ages[i]}")
}
- 處理陣列元素的時候,如果同時需要使用元素的編號與元素值,可以使用下面的for迴圈語法
for ((i, v) in ages.withIndex()) {
println("[$i]: $v")
}
// 顯示:
// [0]: 35
// [1]: 12
// [2]: 27
- 字串陣列
- 所有元素的預設值為「null」,表示並沒有字串物件。
- val <name>: Array<String?> = arrayOfNulls<String>(<元素個數>) val <name> = arrayOfNulls<String>(<元素個數>) val <name>: Array<String?> = arrayOfNulls(<元素個數>)
- 在元素個數不多而且元素值都是已知的情況,可以使用下面的函式,直接建立包含元素資料的字串陣列
- val <name>: Array<String> = arrayOf<String>(String,...) val <name>: Array<String> = arrayOf(String,...) val <name> = arrayOf<String>(String,...) val <name> = arrayOf(String,...)
- 所有元素的預設值為「null」,表示並沒有字串物件。
字串
- 應用程式經常需要顯示一些訊息,例如Android App的對話框,這類的訊息可能是一段包含格式的內容,使用「"""」前後包圍的字串值,可以包含字串值裡面的格式
val literal: String = """
for (c in name) {
print(c)
}
"""
`
println(literal)`// 顯示:
// for (c in name) {
// print(c)
// }
- 如果需要移除前面的空白,可以在字串值的最後呼叫「trimMargin」函式,預設的邊界符號是「|」,你也可以在trimMargin指定一個自定的邊界符號
val literal2: String = """
|for (c in name) {
| print(c)
|}
""".trimMargin()
`
println(literal2)`// 顯示:
//for (c in name) {
// print(c)
//}
val literal3: String = """
#for (c in name) {
# print(c)
#}
""".trimMargin("#")
`
println(literal3)`// 顯示:
//for (c in name) {
// print(c)
//}
列舉
- 宣告列舉類別
// 宣告顏色列舉型態,包含六個顏色成員
enum class Colors01 {
// 列出所有成員的名稱,有六種顏色的名稱,每一個名稱之間使用逗號隔開
LIGHTGREY, BLUE, PURPLE,
GREEN, ORANGE, RED
}
- Kotlin會自動為列舉類別加入一些函式,例如把字串轉換為列舉類別型態
// 把紅、藍、綠顏色名稱字串轉換為列舉型態變數
val c04: Colors01 = Colors01.valueOf("RED")
val c05: Colors01 = Colors01.valueOf("BLUE")
val c06: Colors01 = Colors01.valueOf("GREEN")
`
println("$c04, $c05, $c06")`// 顯示: RED, BLUE, GREEN
- 為列舉類別成員加入對應的資料
enum class 名稱(val 參數名稱: 參數型態) {
成員名稱(對應的值),...
}
// 在宣告的時候加入成員對應資料的參數
enum class Colors02(val value: Int) {
// 在每一個成員名稱後的左右刮號裡面填入對應的資料
LIGHTGREY(0XD3D3D3), BLUE(0X33B5E5), PURPLE(0XAA66CC),
GREEN(0X99CC00), ORANGE(0XFFBB33), RED(0XFF4444)
}
物件與null
- 一般物件宣告預設為不允許指定null值
var name: String = "Simon"
- 若需要指定null值,則需改成
var name2: String? = "Mary"
- 若為可指定null的變數,則必須先經過null值判斷才可使用該變數
// 編譯錯誤,因為可以指定null值的變數
// 不允許直接呼叫函式
// println(name2.length)
`
// 如果先經過null值的判斷...`if (name2 != null) {
// 就可以直接使用
println(name2.length)
}
- 判斷是否為null值變更印出的值,除了用if else判斷式,還可簡化為
// 如果name2是null值,就使用「?:」後面的值
println( name2?.length ?: 0 )
類別(class)
- 類別的宣告
class 類別名稱 constructor(屬性變數宣告, ...)
class Item01 constructor (val id: Long,
var title: String,
var content: String)
- 初始化區塊會在主要建構式接收參數並設定好屬性以後執行
- 如果需要在建立物件的時候,執行一些額外工作,你也可以使用下面的語法,在類別加入其它建構式的宣告。
constructor(參數名稱: 參數型態,...): this(...) {
// 建構式執行的工作
}
繼承(inheritance)
- 使用關鍵字open
- 可讓class擁有可以被繼承的特性
- 可讓fun擁有可以被override的特性
泛型
- 使用泛型宣告的GenericClass類別,可以提供非常大的靈活性,而且避免重複的程式碼。
- 泛型代碼可以是任何有效的識別字,一般的作法會使用下面的規則
- 一個大寫的字母
- 依照用途選擇適合的字母,例如:
- T:型態
- S、U、V…:第二、三、四…種型態
- E:元素
- K:索引鍵型態
- V:資料型態
- 下面的範例也是一個正確的泛型宣告,不過並不建議使用像「QQQ」這樣的泛型代碼
class GenericClass<QQQ> {
private var value : QQQ? = null
`
fun get() : QQQ? {`return value
}
`
fun set(value : QQQ?) {`this.value = value
}
}
- 泛型代碼可以是任何有效的識別字,一般的作法會使用下面的規則
尚未使用泛型的範例
// 取得指定索引編號的元素
fun get(index : Int) : String? {
var result : String? = null
`` if \( index in 0 until size \) {``` result = arr[index]`` `}`
return result``` }
// 取得指定索引編號的元素
fun get(index : Int) : Item? {
var result : Item? = null
`` if \( index in 0 until size \) {``` result = arr[index]`` `}`
return result``` }
....
將上述範例使用泛型
// 取得指定索引編號的元素
fun get(index : Int) : T? {
var result : T? = null
`
if ( index in 0 until size ) {`result = arr[index]
}
`
return result`}