Tina Tang's Blog

在哪裡跌倒了,就在哪裡躺下來

0%

Android筆記(1)-Kotlin簡介

Kotlin為Google宣布的Android官方開發語言

點此可以線上練習編寫Kotlin


Kotlin練習

Hello World

首先我們看到第一個範例:印出Hello, world!

1
2
3
fun main() {
println("Hello, world!")
}
  • 其中,fun代表函式(function),main則是這個函式的名稱,也是Kotlin所需的主函式。
  • 函式名稱後面一律加上兩個括號(),括號中的內容稱為「引數」,或簡短表示為args
  • 引數是指傳送到函式的值,可以是值、變數,甚至是其他函式。
  • 而括號後方的大括號{}包起來的程式,是函式內部用於完成工作的程式碼。
  • println是列印+換行的意思,會指示系統列印一行文字並換行。

建立生日訊息

加入範例程式
  1. 在瀏覽器中開啟 https://developer.android.com/training/kotlinplayground。
  2. 加入範例程式碼:
1
2
3
4
5
fun main() {
println("Happy Birthday, Rover!")
println("You are already 5!")
println("5 is the very best age to celebrate!")
}
建立及使用變數
  1. 將 Rover 的年齡儲存在變數中。
1
val age = 5
  • val 是 Kotlin 使用的特殊字詞,稱為「關鍵字」,age 為變數名稱。

如要輸出該變數的值,而不是文字,只要在前面加上美元符號的大括號內放入變數即可。

1
${variable}
  1. 將程式碼中兩個輸出陳述式的數字 5 改成 age 變數,如下所示
1
2
println("You are already ${age}!")
println("${age} is the very best age to celebrate!")
  1. 更改 age 的值為天數來表示 Rover 的年齡(年齡x365)
1
val age = 5 * 365
  1. 再次執行程式碼,您會發現兩條訊息現在都以天數顯示年齡。
  2. 最後調整一下訊息的文字

現在程式碼:

1
2
3
4
5
6
fun main() {
val age = 5 * 365
println("Happy Birthday, Rover!")
println("You are already ${age} days old!!")
println("${age} days old is the very best age to celebrate!")
}

執行結果:

1
2
3
Happy Birthday, Rover!
You are already 1825 days old!!
1825 days old is the very best age to celebrate!
將文字放入變數
  1. age 的變數下方,新增名為 name 的變數代表壽星名字,並將值設為 “Rover”。
1
val name = "Rover"
  1. 用變數取代生日訊息中的名字 Rover,如下所示。
1
println("Happy Birthday, ${name}!")
  1. 使用 name 變數將 Rover 加入年齡訊息中,如下所示。
1
println("You are already ${age} days old, ${name}!")

現在程式碼:

1
2
3
4
5
6
7
fun main() {
val age = 5 * 365
val name = "Rover"
println("Happy Birthday, ${name}!")
println("You are already ${age} days old, ${name}!")
println("${age} days old is the very best age to celebrate!")
}

執行結果:

1
2
3
Happy Birthday, Rover!
You are already 1825 days old, Rover!
1825 days old is the very best age to celebrate!
使用函式加上生日橫幅的邊框
  1. 建立函式來輸出邊框
1
2
3
fun printBorder() {
println("================================================")
}
  1. main() 函式中呼叫 printBorder() 函式
1
2
3
4
5
6
7
8
9
10
11
12
13
fun main() {
val age = 5 * 365
val name = "Rover"
printBorder()
println("Happy Birthday, ${name}!")
println("You are already ${age} days old, ${name}!")
println("${age} days old is the very best age to celebrate!")
printBorder()
}

fun printBorder() {
println("================================================")
}
  1. printBorder() 函式中,使用 repeat() 重複邊框格式,最後加入 println() 來換行。
1
2
3
4
5
6
fun printBorder() {
repeat(48) {
print("=")
}
println()
}

現在程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fun main() {
val age = 5 * 365
val name = "Rover"
printBorder()
println("Happy Birthday, ${name}!")
println("You are already ${age} days old, ${name}!")
println("${age} days old is the very best age to celebrate!")
printBorder()
}

fun printBorder() {
repeat(48) {
print("=")
}
println()
}

執行結果:

1
2
3
4
5
================================================
Happy Birthday, Rover!
You are already 1825 days old, Rover!
1825 days old is the very best age to celebrate!
================================================
  1. 使用引數變更邊框
  2. 新增名為 border 的變數。
1
val border = "%"
  1. border 變數做為引數,傳遞至對 printBorder() 函式的呼叫中。
1
printBorder(border)
  1. 修改 printBorder() 函式中的引數,並使用 border 作為函式中的變數。
1
2
3
4
5
6
fun printBorder(border: String) {
repeat(48) {
print(border)
}
println()
}
  • 引數的名稱是 border、名稱後方有冒號 : 以及 String (引數的類型)。

現在程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fun main() {
val age = 5 * 365
val name = "Rover"
val border = "%"
printBorder(border)
println("Happy Birthday, ${name}!")
println("You are already ${age} days old, ${name}!")
println("${age} days old is the very best age to celebrate!")
printBorder(border)
}

fun printBorder(border: String) {
repeat(48) {
print(border)
}
println()
}

執行結果:

1
2
3
4
5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Happy Birthday, Rover!
You are already 1825 days old, Rover!
1825 days old is the very best age to celebrate!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1. 將邊框變更為 "'-._,-'" 格式,並新增新變數 timesToRepeat 調整重複次數
1
2
val border = "`-._,-'"
val timesToRepeat = 7
  1. 呼叫 printBorder 函式時,變成需要2個引數
1
printBorder(border, timesToRepeat)
  1. 新曾 printBorder 函式中的引數
1
fun printBorder(border: String, timesToRepeat: Int) {
  • 有多個引數時,以半形逗號 , 分隔引數。

現在程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fun main() {
val age = 5 * 365
val name = "Rover"
val border = "`-._,-'"
val timesToRepeat = 7
printBorder(border, timesToRepeat)
println("Happy Birthday, ${name}!")
println("You are already ${age} days old, ${name}!")
println("${age} days old is the very best age to celebrate!")
printBorder(border, timesToRepeat)
}

fun printBorder(border: String, timesToRepeat: Int) {
repeat(timesToRepeat) {
print(border)
}
println()
}

執行結果:

1
2
3
4
5
`-._,-'`-._,-'`-._,-'`-._,-'`-._,-'`-._,-'`-._,-'
Happy Birthday, Rover!
You are already 1825 days old, Rover!
1825 days old is the very best age to celebrate!
`-._,-'`-._,-'`-._,-'`-._,-'`-._,-'`-._,-'`-._,-'

建立一個多層且點上蠟燭的蛋糕

  • 建立三個函式來繪製一個點上蠟燭的多層蛋糕。
  • 在一個 repeat() 內部使用另一個 repeat(),建立「巢狀迴圈」。
  • 先從大方向開始,再加入細節。這就是所謂的「由上而下開發」。

最後需要完成的蛋糕如下:

1
2
3
4
5
6
7
8
 ,,,,,,,,,,,,,,,,,,,,,,,,
||||||||||||||||||||||||
==========================
@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@

建立 main() 函式
  1. 建立變數 age,並將其設為 24。
  2. 建立第二個變數 layers,並將其設為 5。
  3. 呼叫函式 printCakeCandles(),並傳遞 age。
  4. 呼叫函式 printCakeTop(),並傳遞 age。
  5. 呼叫函式 printCakeBottom(),並傳遞 age 和 layers 的數量。
  • 先將函式註解
1
2
3
4
5
6
7
fun main() {
val age = 24
val layers = 5
// printCakeCandles(age)
// printCakeTop(age)
// printCakeBottom(age, layers)
}
建立 printCakeTop()

printCakeTop() 函式是一行等號,用於輸出蛋糕頂端。
==========================

  1. 建立函式 printCakeTop(),接收 Int 類型的 age 引數。
  2. 使用 repeat() 陳述式輸出單一等號 age+2 次。額外的兩個等號是為了讓蠟燭不會從蛋糕的側面掉下來。
  3. repeat() 完成後,請在結尾輸出一行空白行(換行)。
  4. 移除 main() 中 printCakeTop() 的註解,因為該函式已存在
1
2
3
4
5
6
fun printCakeTop(age: Int) {
repeat(age+2) {
print("=")
}
println()
}
建立 printCakeCandles()

每支蠟燭都由兩個符號組成:半形逗號 (,) 代表燭焰,豎線號 (|) 代表燭體。
,,,,,,,,,,,,,,,,,,,,,,,,
||||||||||||||||||||||||

  1. 建立一個新函式 printCakeCandles(),接收 Int 類型的 age 引數。
  2. 印出一個空格,使蠟燭呈現以下的樣子
1
2
3
 ,,,,,,,,,,,,,,,,,,,,,,,,
||||||||||||||||||||||||
==========================
  1. 使用 repeat() 陳述式輸出一個半形逗號 , 來代表燭焰(重複 age 次),最後換行。
  2. 重複上述步驟來建立第二個 repeat() 陳述式,用來使用豎線號 | 輸出燭體。
  3. 在結尾使用 println() 輸出新的一行。
  4. 移除 main() 中 printCakeCandles() 的註解。
1
2
3
4
5
6
7
8
9
10
11
12
13
fun printCakeCandles(age: Int) {
print(" ")
repeat(age) {
print(",")
}
println()

print(" ")
repeat(age) {
print("|")
}
println()
}
建立 printCakeBottom()

使用這個函式繪製與 age + 2 等寬的蛋糕底部,且畫出的高度包含特定層數。

  • 函式需要兩個引數,一個用於寬度 age,一個用於高度 layers
  • 如要顯示蛋糕底部,請先重複 @ 符號 age + 2 次,即可顯示一層蛋糕。接著,重複輸出一層蛋糕 layers 次。

重複 @ 符號 age + 2 次,繪製一層蛋糕:

  1. 建立內含引數 age 和 layers 的函式 printCakeBottom(),兩個引數都是 Int 類型。
  2. 使用 repeat() 陳述式輸出一層@ 符號 age + 2 次。在結尾輸出空白行。
    如下所示:
1
2
3
4
5
6
fun printCakeBottom(age: Int, layers: Int) {
repeat(age+2) {
print("@")
}
println()
}
  1. 使用巢狀 repeat() 輸出蛋糕層 -> 在函式中的所有程式碼周圍放置第二個 repeat() 陳述式。重複此循環 layers 次
    如下所示:
1
2
3
4
5
6
7
8
fun printCakeBottom(age: Int, layers: Int) {
repeat(layers) {
repeat(age+2) {
print("@")
}
println()
}
}
  1. 移除 main() 中 printCakeBottom() 的註解。

現在程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
fun main() {
val age = 24
val layers = 5
printCakeCandles(age)
printCakeTop(age)
printCakeBottom(age, layers)
}
fun printCakeTop(age: Int) {
repeat(age+2) {
print("=")
}
println()
}
fun printCakeCandles(age: Int) {
print(" ")
repeat(age) {
print(",")
}
println()

print(" ")
repeat(age) {
print("|")
}
println()
}
fun printCakeBottom(age: Int, layers: Int) {
repeat(layers) {
repeat(age+2) {
print("@")
}
println()
}
}

執行結果:

1
2
3
4
5
6
7
8
 ,,,,,,,,,,,,,,,,,,,,,,,,
||||||||||||||||||||||||
==========================
@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@

重要名詞

1. 函式

函式

  • 函式是獨立的程式碼區塊,會執行運算作業並傳回值。在 Kotlin 中,系統會使用fun關鍵字宣告函式,您可以在函式中置入指定或預設的引數。與特定類別相關聯的函式稱為方法

建構函式

  • 在建立類別執行個體時,系統會自動執行名為建構函式的方法。建構函式會負責執行所有必要作業,讓應用程式的其餘部分能使用該物件。舉例來說,針對您要建構的物件,建構函式通常會初始化 (將第一個值填入) 該物件的所有欄位。建立物件的唯一方法是呼叫 (執行) 該物件的建構函式。
  • 建構函式名稱與其所屬的類別名稱相同。一個類別可以有多個建構函式,前提是每個建構函式都要有不同的參數清單。

main()函式

  • Kotlin 程式的 main() 函式是指執行程式的進入點。執行 Kotlin 程式時,開頭一律是main()函式。在 Android 應用程式中,由於您的應用程式程式碼是由 Android 系統執行,因此不必在程式碼中特別指定main()函式。

方法

  • 方法是類別中定義的函式,且與類別的物件執行個體行為相關聯。

參數和引數的差異

  • 函式 (或方法) 中,參數是指函式定義中的變數宣告。呼叫函式時,引數是指您傳送至參數的資料。

2. 類別

類別

  • 類別如同物件的藍圖,可對類別中敘述的所有物件定義通用的屬性 (為變數),以及這些物件的動作 (為名為方法函式)。您必須以 Kotlin 中的class關鍵字來定義類別。
  • 類別就像是建築師的藍圖設計 (而不是房屋本身),也就是建造房屋的指示說明。房屋則是根據該藍圖而建立的實體或物件執行個體。舉例來說,您可能會設定PetDog類別,其中包含寵物名稱和品種的屬性。接著就能建立物件執行個體 myPetDogmyFriendsPetDog。這兩個執行個體的名稱和品種並不相同,但都屬於PetDog類別。

物件

  • 物件導向程式設計中,物件是指類別的特定執行個體,其中物件可以是變數函式和資料結構的組合。

public和private

  • 系統會將類別成員預設為public,表示其他程式碼也能存取。不過,建議您限制對外存取權,僅供必要程式碼進行存取。如果將方法或屬性標記為private,則表示僅供該類別的內部元素存取。這個作法可避免不慎暴露實作部分讓其他呼叫端存取或參照。

抽象類別

  • 抽象類別是 Kotlin 中標示為abstract關鍵字的類別。抽象類別可包含尚未實作的屬性或方法。在這種情況下,您只能在子類別中初始化抽象屬性或實作抽象方法。因此,您無法直接對抽象類別執行個體化。

封裝

  • 封裝是指將邏輯相關的功能整合為同一處。其中一個封裝範例就是類別

3. 命名

駝峰式大小寫

  • 駝峰式大小寫是指將每個字的首字母大寫,並移除每個字之間的所有空格。這是 Kotlin 中對函式變數類別的命名慣例,例如LinearLayoutMainActivitysetOnClickListener