Kotlin เป็นภาษาโปรแกรม ใช้กันอย่างแพร่หลายในหมู่นักพัฒนาซอฟต์แวร์ Android หัวข้อนี้ทำหน้าที่เป็น Kotlin หลักสูตรเร่งรัดที่จะช่วยให้คุณพร้อมทำงานได้อย่างรวดเร็ว
การประกาศตัวแปร
Kotlin ใช้คีย์เวิร์ด 2 คำที่แตกต่างกันเพื่อประกาศตัวแปร: val
และ var
- ใช้
val
สำหรับตัวแปรที่ไม่มีการเปลี่ยนแปลงค่า คุณจะกำหนดค่าใหม่ไม่ได้ ให้กับตัวแปรที่ประกาศโดยใช้val
- ใช้
var
สําหรับตัวแปรที่ค่าเปลี่ยนแปลงได้
ในตัวอย่างด้านล่าง count
เป็นตัวแปรประเภท Int
ที่ได้รับการกำหนด
ค่าเริ่มต้นของ 10
:
var count: Int = 10
Int
เป็นประเภทที่แสดงจำนวนเต็ม ซึ่งเป็นหนึ่งในประเภทตัวเลขจำนวนมาก
แสดงใน Kotlin ได้ เช่นเดียวกับภาษาอื่นๆ คุณสามารถใช้
Byte
, Short
, Long
, Float
และ Double
ขึ้นอยู่กับข้อมูลตัวเลขของคุณ
คีย์เวิร์ด var
หมายความว่าคุณสามารถกำหนดค่าให้กับ count
ใหม่ได้ตามต้องการ สำหรับ
เช่น คุณเปลี่ยนค่าของ count
จาก 10
เป็น 15
ได้
var count: Int = 10
count = 15
อย่างไรก็ตาม ค่าบางค่าไม่จำเป็นต้องเปลี่ยน ลองใช้ String
ที่เรียกว่า
languageName
หากต้องการตรวจสอบว่า languageName
มีค่าเสมอ
ของ "Kotlin" คุณสามารถประกาศ languageName
โดยใช้คีย์เวิร์ด val
ดังนี้
val languageName: String = "Kotlin"
คีย์เวิร์ดเหล่านี้ช่วยให้คุณระบุสิ่งที่เปลี่ยนแปลงได้ ใช้ข้อมูลดังกล่าวเพื่อ
ข้อได้เปรียบของคุณตามความจำเป็น หากต้องกำหนดการอ้างอิงตัวแปรใหม่
ประกาศเป็น var
หรือไม่เช่นนั้น ให้ใช้ val
การอนุมานประเภท
ต่อจากตัวอย่างก่อนหน้านี้ เมื่อคุณกำหนดค่าเริ่มต้นให้กับ
languageName
คอมไพเลอร์ Kotlin จะอนุมานประเภทได้จากประเภทของ
มูลค่าที่กำหนด
เนื่องจากค่าของ "Kotlin"
เป็นประเภท String
คอมไพเลอร์จึงอนุมานว่า
languageName
ยังเป็นString
ด้วย โปรดทราบว่า Kotlin เป็นแอปที่พิมพ์แบบคงที่
ภาษา ซึ่งหมายความว่าประเภทจะได้รับการแก้ไขในเวลาคอมไพล์ และไม่
การเปลี่ยนแปลง
ในตัวอย่างต่อไปนี้ languageName
จะอนุมานเป็น String
คุณจึงไม่สามารถ
เรียกใช้ฟังก์ชันที่ไม่ได้เป็นส่วนหนึ่งของคลาส String
:
val languageName = "Kotlin"
val upperCaseName = languageName.toUpperCase()
// Fails to compile
languageName.inc()
toUpperCase()
คือฟังก์ชันที่เรียกใช้ได้เฉพาะตัวแปรประเภท
String
เนื่องจากคอมไพเลอร์ Kotlin อนุมาน languageName
เป็น String
คุณสามารถโทรหา toUpperCase()
ได้อย่างปลอดภัย อย่างไรก็ตาม inc()
เป็นโอเปอเรเตอร์ Int
ฟังก์ชัน เพื่อให้ไม่สามารถเรียกใน String
วิธีการพิมพ์ของ Kotlin
การอนุมานทำให้คุณได้ทั้งความกระชับและความปลอดภัยในประเภท
ไม่มีข้อมูลความปลอดภัย
ในบางภาษา สามารถประกาศตัวแปรประเภทการอ้างอิงโดยไม่ต้องระบุ ค่าที่ชัดเจนเริ่มต้น ในกรณีเหล่านี้ ตัวแปรมักจะมีค่า Null ตัวแปร Kotlin เก็บค่า Null ตามค่าเริ่มต้นไม่ได้ ซึ่งหมายความว่า ข้อมูลโค้ดต่อไปนี้ไม่ถูกต้อง:
// Fails to compile
val languageName: String = null
ตัวแปรที่จะเก็บค่า Null ต้องเป็นตัวแปรประเภท nullable คุณสามารถ
ระบุว่าตัวแปรเป็นค่าว่างได้โดยใส่ ?
ต่อท้ายประเภท
ในตัวอย่างต่อไปนี้
val languageName: String? = null
เมื่อใช้ประเภท String?
คุณจะกำหนดค่า String
หรือ null
ให้กับได้
languageName
คุณต้องจัดการกับตัวแปรที่เป็นค่าว่างอย่างรอบคอบ ไม่เช่นนั้นจะเสี่ยงให้
NullPointerException
เช่น ใน Java หากคุณพยายามจะเรียกเมธอด
หากเป็นค่าว่าง โปรแกรมของคุณจะขัดข้อง
Kotlin มีกลไกมากมายสำหรับการทำงานกับ Null อย่างปลอดภัย ตัวแปร สำหรับข้อมูลเพิ่มเติม โปรดดู รูปแบบ Kotlin ที่พบบ่อยใน Android: ความสามารถในการเว้นว่าง
เงื่อนไข
Kotlin มีกลไกหลายอย่างในการนำตรรกะตามเงื่อนไขไปใช้ มากที่สุด
โดยทั่วไปจะเป็นคำสั่ง if-else ถ้านิพจน์ที่อยู่ใน
วงเล็บถัดจากคีย์เวิร์ด if
ประเมินได้เป็น true
จากนั้นเขียนโค้ดภายใน
สาขานั้น (เช่น โค้ดที่ตามมาทันทีซึ่งห่อด้วยปีกกา
วงเล็บปีกกา) มิเช่นนั้น ระบบจะเรียกใช้โค้ดภายใน Branch else
if (count == 42) {
println("I have the answer.")
} else {
println("The answer eludes me.")
}
คุณแสดงเงื่อนไขได้หลายรายการโดยใช้ else if
ซึ่งช่วยให้คุณนำเสนอ
ตรรกะที่ซับซ้อนและละเอียดยิ่งขึ้นภายในคำสั่งแบบมีเงื่อนไขเดียว ดังที่แสดงใน
ตัวอย่างต่อไปนี้
if (count == 42) {
println("I have the answer.")
} else if (count > 35) {
println("The answer is close.")
} else {
println("The answer eludes me.")
}
คำสั่งแบบมีเงื่อนไขมีประโยชน์ในการแสดงตรรกะแบบเก็บสถานะ แต่คุณอาจ
จะพบว่าคุณเคยพูดซ้ำเวลาเขียนคำเหล่านั้น ในตัวอย่างข้างต้น คุณ
เพียงพิมพ์ String
ในแต่ละสาขา เพื่อหลีกเลี่ยงปัญหานี้ Kotlin จึงขอนำเสนอ
นิพจน์เงื่อนไข ตัวอย่างสุดท้ายสามารถเขียนใหม่ได้ดังนี้
val answerString: String = if (count == 42) {
"I have the answer."
} else if (count > 35) {
"The answer is close."
} else {
"The answer eludes me."
}
println(answerString)
โดยปริยาย แต่ละ Branch ที่มีเงื่อนไขจะแสดงผลลัพธ์ของนิพจน์ในหน้า
บรรทัดสุดท้าย คุณจึงไม่ต้องใช้คีย์เวิร์ด return
เนื่องจากผลลัพธ์ของ
ทั้ง 3 Branch เป็นประเภท String
ผลลัพธ์ของนิพจน์ if-else คือ
และประเภท String
ด้วย ในตัวอย่างนี้ answerString
ได้รับการกำหนดค่าเริ่มต้น
จากผลลัพธ์ของนิพจน์ if-else การอนุมานประเภทสามารถใช้เพื่อ
ไม่ใส่การประกาศประเภทที่ชัดเจนสำหรับ answerString
แต่ก็มักจะเป็น
แนวคิดที่จะรวมข้อความเหล่านั้น
เพื่อความชัดเจน
เมื่อข้อความแบบมีเงื่อนไขมีความซับซ้อนมากขึ้น คุณอาจลองพิจารณา แทนที่นิพจน์ if-else ด้วยนิพจน์ when ดังที่แสดงใน ตัวอย่างต่อไปนี้
val answerString = when {
count == 42 -> "I have the answer."
count > 35 -> "The answer is close."
else -> "The answer eludes me."
}
println(answerString)
แต่ละสาขาในนิพจน์ when
จะแสดงด้วยเงื่อนไข ซึ่งก็คือลูกศร
(->
) และผลลัพธ์ หากเงื่อนไขทางด้านซ้ายของลูกศร
ประเมินเป็นจริง ผลลัพธ์ของนิพจน์ทางด้านขวาจะเป็น
ส่งคืนแล้ว โปรดทราบว่าการดำเนินการจะไม่ตกหล่นจากสาขาหนึ่งไปยังสาขาถัดไป
โค้ดในตัวอย่างนิพจน์ when
มีฟังก์ชันการทำงานเทียบเท่ากับโค้ดใน
จากตัวอย่างก่อนหน้านี้ แต่น่าจะอ่านได้ง่ายกว่า
เงื่อนไขของ Kotlin ไฮไลต์ฟีเจอร์ที่มีประสิทธิภาพมากกว่านั้น การแคสต์อัจฉริยะ แทนที่จะใช้ตัวดำเนินการ Safe-Call หรือ "ไม่ใช่ค่าว่าง" คุณสามารถตรวจสอบว่า มีการอ้างอิงไปยังค่า Null โดยใช้คำสั่งแบบมีเงื่อนไข เช่น ที่แสดงในตัวอย่างต่อไปนี้
val languageName: String? = null
if (languageName != null) {
// No need to write languageName?.toUpperCase()
println(languageName.toUpperCase())
}
ภายใน Branch แบบมีเงื่อนไข ระบบอาจถือว่า languageName
เป็นค่าว่าง
Kotlin ฉลาดพอที่จะรับรู้ว่ามีเงื่อนไขสำหรับการดำเนินการกับ Branch
คือ languageName
ไม่ได้เก็บค่า Null คุณจึงไม่ต้องใช้
languageName
เป็นค่าว่างภายในสาขานั้น การแคสต์อัจฉริยะนี้ใช้งานได้สำหรับ null
เช็ค
การตรวจสอบประเภท
หรือเงื่อนไขใดๆ ที่เป็นไปตาม
สัญญา
ฟังก์ชัน
คุณจะจัดกลุ่มนิพจน์ตั้งแต่ 1 รายการขึ้นไปลงในฟังก์ชันได้ แทนที่จะทำซ้ำ ชุดนิพจน์เดียวกันทุกครั้งที่คุณต้องการผลลัพธ์ คุณสามารถตัด นิพจน์ในฟังก์ชัน และเรียกใช้ฟังก์ชันนั้นแทน
หากต้องการประกาศฟังก์ชัน ให้ใช้คีย์เวิร์ด fun
ตามด้วยชื่อฟังก์ชัน
ถัดไป ให้กำหนดประเภทอินพุตที่ฟังก์ชันใช้ (หากมี) แล้วประกาศ
ประเภทของเอาต์พุตที่แสดงผล ส่วนเนื้อหาของฟังก์ชันคือตำแหน่งที่คุณกำหนด
นิพจน์ที่เรียกใช้เมื่อเรียกใช้ฟังก์ชัน
ฟังก์ชัน Kotlin ที่สมบูรณ์จากตัวอย่างก่อนหน้านี้มีดังนี้
fun generateAnswerString(): String {
val answerString = if (count == 42) {
"I have the answer."
} else {
"The answer eludes me"
}
return answerString
}
ฟังก์ชันในตัวอย่างด้านบนมีชื่อ generateAnswerString
ทั้งนี้
จะไม่ป้อนข้อมูลใดๆ โดยเอาต์พุตจะเป็นผลลัพธ์ประเภท String
หากต้องการโทรหา
ให้ใช้ชื่อฟังก์ชัน ตามด้วยโอเปอเรเตอร์คำขอ (()
) ใน
ในตัวอย่างด้านล่าง ตัวแปร answerString
เริ่มต้นด้วยผลลัพธ์จาก
generateAnswerString()
val answerString = generateAnswerString()
ฟังก์ชันรับอาร์กิวเมนต์เป็นอินพุตได้ ดังที่ปรากฏในตัวอย่างต่อไปนี้
fun generateAnswerString(countThreshold: Int): String {
val answerString = if (count > countThreshold) {
"I have the answer."
} else {
"The answer eludes me."
}
return answerString
}
เมื่อประกาศฟังก์ชัน คุณสามารถระบุจำนวนอาร์กิวเมนต์และอาร์กิวเมนต์
ประเภทต่างๆ ในตัวอย่างด้านบน generateAnswerString()
รับอาร์กิวเมนต์ 1 รายการที่ชื่อ
countThreshold
ประเภท Int
ภายในฟังก์ชันนี้ คุณสามารถอ้างอิง
โดยใช้ชื่อของอาร์กิวเมนต์
เมื่อเรียกใช้ฟังก์ชันนี้ คุณต้องใส่อาร์กิวเมนต์ภายในฟังก์ชัน วงเล็บของการเรียก:
val answerString = generateAnswerString(42)
การลดความซับซ้อนของการประกาศฟังก์ชัน
generateAnswerString()
เป็นฟังก์ชันที่ค่อนข้างง่าย ฟังก์ชันดังกล่าวจะประกาศว่า
ตัวแปร แล้วจึงแสดงผลทันที เมื่อผลลัพธ์ของนิพจน์เดียว
ที่แสดงผลจากฟังก์ชัน คุณสามารถข้ามการประกาศตัวแปรภายใน
ส่งคืนผลลัพธ์ของนิพจน์ if-else ที่มีอยู่ในฟังก์ชัน เช่น
ที่แสดงในตัวอย่างต่อไปนี้
fun generateAnswerString(countThreshold: Int): String {
return if (count > countThreshold) {
"I have the answer."
} else {
"The answer eludes me."
}
}
นอกจากนี้คุณยังแทนที่คีย์เวิร์ดส่งคืนด้วยโอเปอเรเตอร์งานที่กำหนดได้ด้วย โดยทำดังนี้
fun generateAnswerString(countThreshold: Int): String = if (count > countThreshold) {
"I have the answer"
} else {
"The answer eludes me"
}
ฟังก์ชันที่ไม่ระบุชื่อ
บางฟังก์ชันไม่จำเป็นต้องมีชื่อ ฟังก์ชันบางอย่างจะระบุโดยตรงมากขึ้นโดย อินพุตและเอาต์พุต ฟังก์ชันเหล่านี้เรียกว่าฟังก์ชันที่ระบุตัวบุคคล คุณ สามารถเก็บการอ้างอิงไปยังฟังก์ชันนิรนาม โดยใช้การอ้างอิงนี้เพื่อ เรียกใช้ฟังก์ชันไม่ระบุตัวตนในภายหลัง นอกจากนี้ คุณยังส่งต่อข้อมูลอ้างอิงเกี่ยวกับ เช่นเดียวกับข้อมูลอ้างอิงประเภทอื่นๆ
val stringLengthFunc: (String) -> Int = { input ->
input.length
}
ฟังก์ชันที่ไม่ระบุชื่อสามารถมีนิพจน์กี่นิพจน์ก็ได้ เช่นเดียวกับฟังก์ชันที่มีชื่อ ค่าที่แสดงผลของฟังก์ชันคือผลลัพธ์ของนิพจน์สุดท้าย
ในตัวอย่างข้างต้น stringLengthFunc
มีการอ้างอิงถึงบุคคลนิรนาม
ฟังก์ชันที่จะรับ String
เป็นอินพุตและแสดงผลความยาวของอินพุต
String
เป็นเอาต์พุตประเภท Int
ด้วยเหตุนี้ ประเภทของฟังก์ชันคือ
แสดงเป็น (String) -> Int
อย่างไรก็ตาม โค้ดนี้จะไม่เรียกใช้ฟังก์ชัน
หากต้องการดึงผลลัพธ์ของฟังก์ชัน คุณจะต้องเรียกใช้ฟังก์ชัน
ฟังก์ชันที่มีชื่อ คุณต้องระบุ String
เมื่อโทรหา stringLengthFunc
เป็น
ที่แสดงในตัวอย่างต่อไปนี้
val stringLengthFunc: (String) -> Int = { input ->
input.length
}
val stringLength: Int = stringLengthFunc("Android")
ฟังก์ชันที่มีลำดับสูงกว่า
ฟังก์ชันหนึ่งสามารถใช้ฟังก์ชันอื่นเป็นอาร์กิวเมนต์ได้ ฟังก์ชันที่ใช้อื่นๆ เป็นอาร์กิวเมนต์เรียกว่าฟังก์ชันลำดับสูงกว่า รูปแบบนี้ มีประโยชน์ในการสื่อสารระหว่างองค์ประกอบต่างๆ ในลักษณะเดียวกับที่คุณอาจใช้ Callback ใน Java
ต่อไปนี้คือตัวอย่างของฟังก์ชันที่มีลำดับสูงกว่า
fun stringMapper(str: String, mapper: (String) -> Int): Int {
// Invoke function
return mapper(str)
}
ฟังก์ชัน stringMapper()
จะใช้ String
พร้อมด้วยฟังก์ชันที่
ดึงค่า Int
จาก String
ที่คุณส่งเข้าไป
คุณสามารถเรียก stringMapper()
ได้โดยการส่ง String
และฟังก์ชันที่
เป็นไปตามพารามิเตอร์อินพุตอื่นๆ ซึ่งก็คือฟังก์ชันที่ใช้ค่า String
เป็น
อินพุตและเอาต์พุต Int
ดังที่แสดงในตัวอย่างต่อไปนี้
stringMapper("Android", { input ->
input.length
})
หากฟังก์ชันที่ไม่ระบุตัวตนเป็นพารามิเตอร์สุดท้ายที่กำหนดไว้ในฟังก์ชัน คุณจะดำเนินการต่อไปนี้ได้ ส่งภายนอกวงเล็บที่ใช้ในการเรียกใช้ฟังก์ชัน ดังที่แสดงใน ตัวอย่างต่อไปนี้
stringMapper("Android") { input ->
input.length
}
ฟังก์ชันที่ไม่ระบุชื่อจะอยู่ในไลบรารีมาตรฐานของ Kotlin สำหรับ ข้อมูลเพิ่มเติม โปรดดู ฟังก์ชันลำดับสูงกว่าและ Lambda
ชั้นเรียน
ประเภททั้งหมดที่พูดถึงจนถึงขณะนี้ได้รวมอยู่ในการเขียนโปรแกรม Kotlin แล้ว
ภาษา หากต้องการเพิ่มประเภทที่กำหนดเอง คุณสามารถกำหนดชั้นเรียน
โดยใช้คีย์เวิร์ด class
ดังที่แสดงในตัวอย่างต่อไปนี้
class Car
คุณสมบัติ
ชั้นเรียนจะแสดงสถานะโดยใช้พร็อพเพอร์ตี้ ต
property คือ
ตัวแปรระดับคลาสที่อาจมี Getter, Setter และ Backing Field
เนื่องจากรถยนต์ต้องมีล้อจึงจะขับขี่ คุณเพิ่มรายการวัตถุ Wheel
เป็น
ของ Car
ดังที่แสดงในตัวอย่างต่อไปนี้
class Car {
val wheels = listOf<Wheel>()
}
โปรดทราบว่า wheels
เป็น public val
ซึ่งหมายความว่า wheels
สามารถเข้าถึงได้จาก
อยู่นอกชั้นเรียน Car
และไม่สามารถเปลี่ยนการมอบหมายได้ ถ้าคุณต้องการขอรับ
ของ Car
คุณต้องเรียกใช้ตัวสร้างก่อน จากนั้นคุณสามารถ
เข้าถึงทุกพร็อพเพอร์ตี้ที่เข้าถึงได้ง่าย
val car = Car() // construct a Car
val wheels = car.wheels // retrieve the wheels value from the Car
หากต้องการปรับแต่งวงล้อ คุณสามารถกำหนดผู้ผลิตเอง ระบุวิธีเริ่มต้นพร็อพเพอร์ตี้คลาส ดังนี้
class Car(val wheels: List<Wheel>)
ในตัวอย่างข้างต้น ตัวสร้างคลาสจะใช้ List<Wheel>
เป็น
อาร์กิวเมนต์ตัวสร้างและใช้อาร์กิวเมนต์นั้นเพื่อเริ่มต้น wheels
ฟังก์ชันและการห่อหุ้มข้อมูลของชั้นเรียน
ชั้นเรียนใช้ฟังก์ชันเพื่อสร้างโมเดลพฤติกรรม ฟังก์ชันต่างๆ สามารถแก้ไขสถานะ เพื่อแสดงเฉพาะข้อมูลที่คุณต้องการเปิดเผย การควบคุมการเข้าถึงนี้เป็นส่วนหนึ่งของ แนวคิดเชิงวัตถุขนาดใหญ่ที่เรียกว่าการสรุป
ในตัวอย่างต่อไปนี้ พร็อพเพอร์ตี้ doorLock
จะถูกเก็บเป็นส่วนตัวจากอะไรก็ได้
นอกชั้นเรียน Car
คุณต้องโทรหา unlockDoor()
เพื่อปลดล็อกรถ
การส่งฟังก์ชันในคีย์ที่ถูกต้อง ดังที่ปรากฏในตัวอย่างต่อไปนี้:
class Car(val wheels: List<Wheel>) {
private val doorLock: DoorLock = ...
fun unlockDoor(key: Key): Boolean {
// Return true if key is valid for door lock, false otherwise
}
}
หากต้องการปรับแต่งวิธีอ้างอิงพร็อพเพอร์ตี้ คุณสามารถระบุ
Getter และ Setter ที่กำหนดเอง เช่น หากคุณต้องการแสดงพร็อพเพอร์ตี้
getter ขณะจำกัดการเข้าถึงตัวตั้งค่า คุณสามารถระบุตัวตั้งค่านั้นเป็น
private
:
class Car(val wheels: List<Wheel>) {
private val doorLock: DoorLock = ...
var gallonsOfFuelInTank: Int = 15
private set
fun unlockDoor(key: Key): Boolean {
// Return true if key is valid for door lock, false otherwise
}
}
คุณสร้างคลาสที่ สร้างแบบจำลองวัตถุทุกประเภท
ความสามารถในการทำงานร่วมกัน
ฟีเจอร์ที่สำคัญที่สุดอย่างหนึ่งของ Kotlin คือความสามารถในการทํางานร่วมกันแบบไหลกับ Java เนื่องจากโค้ด Kotlin คอมไพล์ลงไปเป็นไบต์โค้ด JVM โค้ด Kotlin จึงสามารถเรียกใช้ ลงในโค้ด Java โดยตรง หรือกลับกัน ซึ่งหมายความว่าคุณสามารถใช้ประโยชน์ ไลบรารี Java ที่มีอยู่แล้ว โดยตรงจาก Kotlin นอกจากนี้ ส่วนใหญ่ของ API ของ Android เขียนขึ้นใน Java ซึ่งคุณจะเรียกใช้ได้โดยตรงจาก Kotlin
ขั้นตอนถัดไป
Kotlin เป็นภาษาที่มีความยืดหยุ่นและใช้งานได้จริง ซึ่งมีการสนับสนุนและแรงกระตุ้นที่เพิ่มขึ้นเรื่อยๆ พ เราขอแนะนำให้คุณลองหากคุณยังไม่ได้ทำ ขั้นตอนถัดไป โปรดดูที่ ในเอกสารประกอบของ Kotlin อย่างเป็นทางการ รวมถึงคำแนะนำเกี่ยวกับวิธีการใช้ รูปแบบ Kotlin ทั่วไปในแอป Android