Wasith T. (Bai-Phai)
odds.team
Published in
2 min readJul 22, 2017

--

การเขียน guard let, if let, และ as? แบบ Swift ใน Kotlin

guard เอาไว้ตรวจค่า ว่าเป็นไปอย่างต้องการหรือป่าว ซึ่งถ้าไม่ตรงตามเงื่อนไขก็จะขับไล่มันออกจาก function โดยการ return, throw exception ออกจาก function ไป หรือ break ออกจาก loop

ตัวอย่างเช่นเชคว่า null มั้ย

// ===== Swift =====
guard wrappedThing != nil else {
return
}
// ===== Kotlin =====
wrappedThing ?: return

ซึ่งเมื่อใช้ guard แล้วถ้า expression เป็น true จะกระโดดไปทำข้างใต้ block ของ guard เลยแต่ถ้าไม่เป็นจริง จะทำใน block ของ guard แล้ว จึงบังคับให้ออกจาก function โดยการ return หรือ throw exception ทันที

ที่นี่ถ้าอยากเอาตัว unwrapped หรือตัวที่ตรวจแล้วว่าไม่ใช่ nil หรือ null มาใช้สามารถเขียนได้โดยใช้

// ===== Swift =====
guard let unwrappedThing = wrappedThing else {
return
}
print(unwrappedThing)
// ===== Kotlin =====
wrappedThing ?: return
println(wrappedThing)
// เสร็จแล้ว wrappedThing จะกลายเป็น non-optional ทันที
// สามารถเรียกใช้ wrappedThing ได้เลย ไม่จำเป็นต้อง ไป assign ให้ตัวแปลอื่น

// ใน Swift ก็สามารถใช้ชื่อแปลเดียวกันมารับค่าก็ได้ เช่น
guard let wrappedThing = wrappedThing else {
return
}
print(wrappedThing)

ในการเขียน guard ใน Swift นั้น ไม่สามารถใช้ตัวแปล unwrappedThing ใน block ของ guard ได้ แต่จะใช้ได้ใต้จาก guard อีกทีหนึ่ง

ถ้าอยากเขียนให้ทำอะไรซักอย่างก่อนออกจาก function

// ===== Swift =====
guard let unWrappedThing = wrappedThing else {
print("[!] You wrappedThing is nil")
return
}
print(unWrappedThing)// ===== Kotlin =====
if (wrappedThing == null) {
println("wrappedThing is null")
return
}
println(wrappedThing)// เหมือนกันกับข้างบน wrappedThing จะกลายเป็น non-optional ทันที
// เว้นแต่ wrappedThing เป็นตัวแปล (var) ไม่ใช่ค่าคงที่ (val)
// แล้วถูก assign ค่า null เข้าไป Editor จะรู้ทันทีว่าเป็น optional อีกครั้ง

เนื่องจาก let เป็น immutable type คือเป็น final แล้วไม่สามารถแก้ไขค่าได้ หากต้องการแก้ไขค่าได้ ก็สามารถใช้ guard var ได้
แต่เราไม่แนะนำ หากต้องการแก้ค่าจริง ๆ ควรนำไปใส่ในตัวแปลอื่นดีกว่า

แล้วถ้าอยากใช้ if let แบบ swift ใน kotlint สามารถเขียนได้ตามนี้

เกริ่น if let ใน swift ใช้คล้าย ๆ guard let คือใช้ unwrap ค่าจาก optional เป็น non-optional ได้

// ===== Swift =====
if let unwrappedThing = wrappedThing {
print("wrappedThing is not nil")
} else {
print("wrappedThing is nil")
}

// ===== Kotlin =====
if (wrappedThing != null) {
println("wrappedThing is not null")
} else {
println("wrappedThing is null")
}

แต่ต่างจาก guard let ตรงที่ตัวแปลที่ถูก unwrap ออกมาแล้วจะสามารถใช้ได้แค่ใน scope หรือ block ของ if นั้น ๆ เท่านั้น และถ้าได้ค่าเป็น nil หรือ null จะไม่ทำใน block นั้นเลย

ทั้งนี้ถ้าต้องการ mutate ค่า สามารถใช้ if var ได้เช่นเดียวกับ guard var ได้เช่นกัน แต่ก็ไม่แนะนำ

แถม

การ downcasting, หรือเชคประเภทตัวแปลใน Swift และ Kotlin

// ===== Swift =====
if let text = optionalText as? String {
print("optionalText is not nil and it is \(text)")
} else {
print("optionalText is nil")
}

// ===== Kotlin =====
if optionalText is String {
println("optionalText is not null and it is ${optionalText}")
} else {
println("optionalText is null")
}

ถ้า downcasting ค่า เนื่องจามีกการใช้งาน polymorphism ใน Swift ใช้ as ใน Kotlin ใช้ is

  • ใน Kotlin ใช้ is ทั้ง downcasting และ check type
  • ใน Swift ใช้ as? เพื่อทำ downcasting ใช้ is เพื่อ check type

ที่เห็นใน Swift ใช้ as? (สังเกตุที่ question mark) เนื่องจากว่า ถ้า cast ค่าไม่ได้จะให้ return ค่า nil เป็น default ซึ่งก็จะไม่เข้าเงื่อนไขของ if let ว่าค่าต้องไม่เป็น nil ถึงจะทำงานใน block

ปล. หากมีข้อสงสัยหรือข้อเสนอแนะ สามารถแนะนำได้เลยนะครับผม
สวัสดีครับ

--

--

Wasith T. (Bai-Phai)
odds.team

ตบมือเป็นกำลังใจให้ผมด้วยนะครับ 😘