How to Kotlin ภาษานี้มันเขียนยังไงนะ จาก Google I/O 18

Android May 28, 2018

ตอนต้นเขาได้เกริ่นนำไว้ว่า เป็นภาษา Kotlin เป็น 1 ในภาษาที่ Developer ทั้งหลายรักสุดๆบนโลกใบนี้ เอ๊ะมันจะจริงไหมน๊าาา

Session นี้ คงจะไม่มีใครเหมาะไปกว่าคุณ Andre Breslov ผู้เป็น Lead Kotlin Language Designer จาก Jetbrains อีกแล้วแหละ ชื่อตำแหน่งก็การันตีขนาดนี้แล้วนะ แถมยังโชว์ live code ให้ดูเป็นบุญตาด้วยหล่ะ

https://www.youtube.com/watch?v=6P20npkvcb8

เริ่มต้นด้วยการด้วยการเปรียบเทียบโค้ดชุดนี้ ก็น่าจะรู้กันอยู่แล้วว่าฝั่งซ้ายเป็น Kotlin และฝั่งขวาเป็น Java แต่คนเขียน Kotlin คงรู้อยู่แต่ใจดีว่า ปกติเราไม่ได้เขียนแบบนี้นี่หว่าาาเนอะ

แล้วเขาก็ได้โชว์การก็อปโค้ด Java จากฝั่งขวา ไปยัง Kotlin ซึ่ง Android Studio ที่น่ารักต้องติดตั้ง plug-in ก่อนนะ มันจะ convert Java เป็น Kotlin เป็นแบบนี้ one class, two properties

นี่เป็นแค่นํ้าจิ้ม

จะสรุปแบบละเอียดก็ไม่ไหวแหะ เนื้อหาเยอะและแน่นมาก กลัวเขียนแล้วยาวไป งั้นขอสรุปสั้นๆว่ามีอะไรที่เราควรรู้เกี่ยวกับ Kotlin บ้าง

ตัวอย่างต่อมา เรามาดู class นี้กัน ซึ่งฝั่งซ้ายมันเป็น Java style อยู่เลยแหะ เนื่องจากหลายๆภาษามันไม่สามารถ return ค่ามากกว่า 2 ค่าได้ (ที่ทำได้ถ้าจำไม่ผิดนะ ภาษาที่เคยเขียนมา มี python กับ MATLAB อ่ะ แล้วมีเจ้า golang ที่เรายังไม่เคยลองเขียน แต่น้องเตอเติ้ลเคยเขียนแล้ว และ gopher น่ารักดี เดี๋ยวๆ) ฝั่งขวาเลยสร้าง class ขึ้นมาชื่อว่า FullName รับค่าชื่อและนามสกุลมา และสามารถ return ค่าออกมาเป็น class นี้ได้เลย เย้ (มอง class เป็น object ตังนึงนะ)

และเวลาอ้างอิงแต่ละตัวก็ใช้ . แล้วเรียกชื่อมันมาได้เลย ไม่ต้องไปเรียกแบบ array นะ มันเชยแล้ว

แต่เวลารันแล้วมันได้ Equals doesn’t work ดังนั้นเลยทำเป็น data class ซะ โดยใส่ data ไว้ข้างหน้า เจ้า compiler จะ generate ตัว equal ,hash code และอื่นๆตามมาด้วย

ต่อมาเป็นเรื่องของ property นั่นคือ getter และ setter นั่นเอง ซึ่งเราสามารถเขียน get() สำหรับ getter และ set() สำหรับ setter และข้างในสามารถใส่อะไรก็ได้ตามใจเราเลย ส่วน field คือตัวแปรที่รับค่าเอาไปเขียนใน backend storage

เห็นเจ้า getter เมื่อกี้บ้างไหม เราสามารถเปลี่ยนเป็นเจ้า lazy เพื่อ initialized อะไรบางอย่าง อย่างในที่นี้ก็ init ค่าของเจ้าตัวแปร os ได้เลยย

ใช้เจ้า Delegates.observable เพื่อ notify เวลาที่มีอะไรบางอย่างเปลี่ยนแปลงไป สามารถเอาไปใช้ที่อื่นๆได้ด้วย อารมณ์เหมือนเก็บ state ไว้ และเราไม่ควรใช้ getter และ setter เปลืองๆแบบนั้น

แล้วก็อย่าเขียนแบบนี้ใน Kotlin นะ พี่แกขอไว้ เพราะ class นี้ยัดทุกอย่างลงไปในนี้หมดเลยยย ดังนั้นจากภาพนี้ เปลี่ยน class StringUtil เป็น Object StringUtil และเวลาเรียกใช้จะเรียก StringUtil.getFirstWord(“Jane Doe”) แบบนี้

เอ้ออออ ภาษา Kotlin ไม่มี static class นะเออ

มีอีกอย่างนึง เราสามารถ init parameter ของ function ได้ด้วยนะ ถ้าเราเรียก function นี้ แล้วค่าเป็น null ดังนั้น ค่าของ parameter นั้น เป็นค่า default ที่เรากำหนดไว้นั่นเอง

fun getFirstWord(s: String, separator: String = " ") {...}

เวลาใช้งาน อาจจะใส่ไม่ครบ parameter ก็ได้นะ ถ้าเจ้า parameter ถูก init ค่าเบื้องต้นไว้แล้วอะนะ หรือใส่ค่าตัวแปรไปแบบนี้ก็ได้

getFirstWord("Jane Doe")
getFirstWord("Jane Doe", separator = ",")

จริงๆเขามีเล่นท่าแปลกๆอยู่ ไปดูกันเองแล้วกัน ฮ่าๆ……

การเขียน Recursion (เรียกใช้งานซํ้าของเดิม) ใน Kotlin ที่มี hierarchy วุ่นวายๆ

เราจะเห็นสีต่างๆใน editor เนอะ สีเทาคือ compiler บอกว่าไม่จำเป็นต้องใส่มัน ส่วนสีเขียว highlight แบบนี้ คือ compiler จะ cast type ให้เราเอง

มีทริคที่ทำให้โค้ดสั้นลงฉบับ Kotlin คือ 
ใช้ forEach แทน for ปกติ และใช้ when แทน if

ใช้ sealed class แทน abstract class เพื่อที่เราสามารถสร้าง sub-class ในไฟล์นี้ได้

https://kotlinlang.org/docs/reference/sealed-classes.html

ใช้ with ในการ assign ค่าต่างๆ หรือ update attribute หรือ something like that ใน object ตัวนึง ซึ่งท่ามันจะคล้ายๆกับ Pascal ซึ่งเป็นภาษาแรกที่ speaker เขียนด้วยแหะ แต่เหมือนเราไม่ทันภาษานี้นะ 555

และเลิกต่อ string แบบ + ซะที มันเชยแล้ว มันต้องแบบนี้เว้ยย ใช้ $ ต่อหลังด้วยชื่อตัวแปร เป็นการอ้างอิงค่าของตัวแปรตัวนั้นๆ

with (ex) {
    println("a = $a, b= $b, c = $c")
}

ปกติเราจะประกาศตัวแปร HashMap แล้วมาใส่ทีละตัว ดังนั้นเลิกทำซะใน Kotlin ใส่ทีเดียวไปแบบนี้เลย แบบนี้เลย ง่ายเนอะ ใส่รวดเดียวไปเลย

val map = mapOf(Pair("k1", 1), Pair("k2", 2), Pair("k3", 3))

ซึ่งเจ้า Pair() จะ map key กับ value เข้ามาอยู่ด้วยกันในที่เดียว และสามารถเขียนได้อีกท่านึงที่สั้นกว่าเดิม คือ

val map = mapOf("k1" to 1, "k2" to 2, "k3" to 3)

เวลาวน loop แอบคล้ายๆ python ที่เป็นเจ้า List สามารถเรียก key กับ value จากใน loop ได้ และท่าการทำก็คล้ายกันด้วย

for((key, value) in map.entries) { 
    println("$key -> $value")
}

ส่วนการเขียน statement ในกรณีที่ตรวจ condition ก่อนแล้วใส่ค่า เราจะเขียน if-else แล้วกำหนดค่าว่าตัวแปรนี้เราจะ assign ค่าอะไรไป ซึ่งใน kotlin ก็ใช้เจ้า when แทน if-else พวกนี้ ดังนั้นโค้ดจะสั้นลงไปเยอะ แบบนี้

อยากอ่านแบบคร่าวๆว่าเจ้า when ทำอะไรได้บ้าง อ่านบทความข้างล่างนี้เลยจ้า

Expression ง่ายๆ สไตล์ Kotlin
โพสนี้สั้นมากบอกเลย ไม่มีอะไรพิสดาร ผมก็ไม่มั่นใจจะมาเขียนทำไม…

และเราก็สามารถใช้ return พร้อมกันกับ when ได้ด้วย แบบนี้

fun test(e: Example): String {
    return when (e.a) {
       1, 2, 3 -> "Odd"
       in setOf(2, 3, 4) -> "Even"
       else -> "Too big"
    }
}

เอ๊ะยังยาวไปนิด แบบนี้แล้วกัน

fun test(e: Example) = when (e.a) {
    1, 2, 3 -> "Odd"
    in setOf(2, 3, 4) -> "Even"
    else -> "Too big"
}

เวลาเราเห็นโค้ด Kotlin ที่มี ? ห้อยท้าย น่าจะรู้อยู่แล้วเนอะว่าตัวแปรนี้เป็น nullable type คือเป็นได้ทั้งมีค่าปกติ และค่า null

ส่วน elvis operator ที่มีหน้าตาแบบนี้ ?: แล้วมันทำงานอย่างไรหล่ะ?

val s = str ?: ""

มันจะ check ค่าทางซ้ายก่อน ในที่นี้คือ str ว่ามีค่าเป็นเท่าไหร่ ถ้าเป็น null ให้คืนค่าหลังเจ้า elvis ออกมา ในที่นี้คือ string ว่างๆตัวนึงนั่นเอง

เราสามารถเขียน function การทำงาน ที่โค้ดดูซับซ้อน ให้ดูอ่านเข้าใจง่ายขึ้น

ใช้ it แทน object ที่ถูกอ้างอิง และ also ใช้เขียน semi-function อาจจะใช้ตอน debugging ก็ได้นะ ข้อดีคือ ไม่ต้องเขียนเพิ่มให้ซับซ้อน

ดูเจ้า function repeat นั้นสิ รับค่าเป็น int มาปกติ ที่พิเศษคือ รับเจ้า body ที่เป็น type Unit มาด้วย ช่างมันไปก่อนเน้อ เวลาเอาเจ้า repeat ไปใช้ สามารถใช้ได้แบบในรูป แล้วยังให้ทำงานเพิ่มได้ เช่น แสดงผล

เราสามารถใส่เจ้า inline function โดยที่เราไม่ต้องเปลี่ยนโค้ด พอมาเปิด bytecode พบว่าเป็น for loop ธรรมดาอันนึง

Mindset อย่างนึงที่เปลี่ยนไปสำหรับคนที่เขียน Java แล้วย้ายไป Kotlin คือ เราสามารถใช้เจ้า lambda ได้ตามใจชอบเลย

พักไปชมสิ่งที่น่าสนใจสักแปปก่อนนะ

สุดท้ายมาในเรื่องของเจ้า Thread ซึ่งมาในแบบ 100 x 100 หรือ 100,000 thread นั่นเอง การทำงานในบริมาณแบบนี้ แอปก็ พัง ไปตามคาด เพราะ memory ไม่พอหน่ะสิ การใช้ memory ถือเป็น cost อย่างนึงนะ

ดังนั้นจึงมีคนมาช่วยแก้ปัญหาเรื่องนี้ นั่นคือ เจ้า Coroutine นั่นเอง ซึ่งทำงานแบบ asynchronous ซึ่งใช้ 100,000 coroutines ก็ไม่มีปัญหาเรื่อง memory เพราะใช้น้อยมาก

ปล. เรื่องรองสุดท้ายใน session นี้คือเรื่อง Callback แต่อยากให้ไปดูเองมากกว่าอ่ะ ซึ่งเขาใช้เจ้า coroutine ในการเรียก request จาก API

ปิดท้ายด้วย buildSequence เป็นการสร้างเจ้า sequence มาตัวนึง และข้างในจะใส่อะไรไปก็ได้ ส่วน yield เป็น statement ตัวนึง

ถ้าอยากรู้จักเจ้า sequence ให้มากขึ้น อ่านบล็อกนี้เลยจ้า

จัดการข้อมูลด้วย Sequence
ทุกท่านคงจะคุ้นเคยกันดีกับ data type ประเภท Collection ที่ใช้ในการเก็บชุดข้อมูลประเภท type เดียวกัน ซึ่งก็มี implementation มากมาย เช่น ArrayList, HashMap Sequence คือ type ที่สามารถเข้าถึงข้อมูลแบบ…

วิดีโอย้อนหลังงาน Google I/O 2018 เฉพาะของ Android นะ

สุดท้ายฝากร้านกันสักนิด ฝากเพจด้วยนะจ๊ะ

อย่าลืมกด like กด share บทความกันด้วยนะคะ :)

Posted by MikkiPastel on Sunday, 10 December 2017

Tags

Minseo Chayabanjonglerd

I am a full-time Android Developer and part-time contributor with developer community and web3 world, who believe people have hard skills and soft skills to up-skill to da moon.