Value and Reference Types in Swift

ประเภทของ Instance (of Custom Type) ใน Swift แบ่งออกเป็น 2 ประเภทคือ
  • Value Type หมายถึง instance นั้นจะจัดการ data ของตัวเอง ไม่มีใครมาเปลี่ยนแปลง data ของตัวเองได้ ซึ่งใน Swift ข้อมูลที่เป็น Value Type ก็เช่น struct, enum และ tuple
  • Reference Type จะหมายถึงในทางกลับกันคือ data ที่อยู่ใน instance จะทำการแชร์กับตัวแปรอื่นๆ ที่ถูก reference ไปด้วยซึ่งถ้าสร้าง Custom Type ด้วย class จะเป็น Reference Type
ใน Blog นี้เราจะมาว่ากันถึงข้อดีของทั้งสองแบบ และการเลือกว่าจะใช้อันไหนดี

What's the Difference ?

สิ่งที่แตกต่างกันอย่างชัดเจนของ Value type นั่นคือการ copy ซึ่งจะเห็นผลในเรื่องของ ผลกระทบของการกำหนดค่า, การกำหนดค่าเริ่มต้น และการส่งผ่าน arguments มาลองดูตัวอย่างการสร้าง instance ที่เป็น Value type กัน


ในทางกลับกัน Reference Type จะเป็นการสร้าง instance แบบแชร์ข้อมูลกัน โดยหลังจากที่มีการกำหนดค่าเกิดขึ้น instance ทั้งสองตัวจะอ้างอิงไปหาข้อมูลตัวเดียวกัน และสามารถเปลี่ยนค่าของกันและกันได้ เช่น ถ้าเราเปลี่ยนแปลงในตัวแปรตัวที่สอง ตัวแรกจะมีผลกระทบด้วย


The Role of Mutation in Safety

หนึ่งในเหตุผลสำคัญที่จะเลือก Value Type ก่อน Reference Type คือเหตุผลง่ายๆ ที่ว่า ถ้า instance ทุกตัวแยกขาดจากกันหมด เราสามารถเชื่อได้ว่าจะ "ไม่" เกิดเหตุการณ์ที่มีการเปลี่ยนแปลงข้อมูลที่ทำให้เกิดความผิดพลาดของโปรแกรมโดยที่เราไม่รู้ได้ และที่สำคัญมากเลยคือมันจะช่วยในเรื่องของ multi-thread programming เวลาที่ thread อื่นๆ ทำการเปลี่ยนแปลงข้อมูลบาง instance ของเรา ซึ่งมันมีโอกาสจะสามารถสร้าง bug ที่ร้ายแรงและยากต่อการแก้ไขได้

เนื่องจากความแตกต่างของ Type ทั้งสองนั้นถูกกำหนดในแนวทางของ "สิ่งที่จะเกิดขึ้นเมื่อเราเปลี่ยนแปลงข้อมูล" จะมีอยู่กรณีหนึ่งที่มันทับซ้อนกันนั่นคือ เมื่อ instance ใดๆ ก็ตามไม่มีข้อมูลที่สามารถเขียน หรือเปลี่ยนแปลงได้ (เช่น class ที่มีแต่ read-only property) ทั้ง Value และ Reference Type จะเหมือนกันทุกประการ

คุณลองคิดดีๆ มันอาจจะมีประโยชน์ก็ได้นะ ที่จะมี class ที่ไม่มีการเปลี่ยนแปลงแน่นอน นี่อาจจะทำให้เราใช้งาน NSObject บน Cocoa Framework ง่ายขึ้น ซึ่งทุกวันนี้เราสามารถเขียน class ที่ไม่สามารถเปลี่ยนแปลงบน Swift ได้โดยประกาศ property ให้เป็นแบบที่อ่านได้อย่างเดียว แต่ในความจริงแล้ว เกือบทุก class ใน Cocoa ตัวอย่างเช่น NSURL ก็ถูกออกแบบให้เป็น class ที่ไม่สามารถเปลี่ยนแปลงได้นะ อย่างไรก็ตาม Swift ในตอนนี้ยังไม่สามารถทำให้ class ที่ถูกสร้างขึ้นเป็น class ที่เปลี่ยนแปลงไม่ได้ด้วยกลไกของตัวภาษา คงยังต้องรอต่อไป หรือไม่ก็เปลี่ยนไปใช้ struct หรือ enum แทน

How to Choose?

ดังนั้น ถ้าคุณต้องการสร้าง Custom Type ใดๆ ขึ้นมาใหม่ จะตัดสินใจยังไงว่าจะใช้แบบไหน ? เวลาที่คุณทำงานกับ Cocoa Framework แทบจะทุก Class จะสืบทอดมาจาก NSObject ดังนั้นเราต้องใช้ class ส่วนในกรณีอื่นๆ นี่เป็นแนวทางเล็กๆ น้อยๆ

ใช้ Custom Type ที่เป็น Value Type เมื่อ
  • การเปรียบเทียบข้อมูลสองตัวจะใช้เครื่องหมาย ==
  • ต้องการให้ instance แต่ละตัวแยกขาดจากกันจริงๆ
  • ข้อมูลนั้นจะถูกใช้บนหลายๆ thread
ใช้ Custom Type ที่เป็น Reference Type เมื่อ
  • การเปรียบเทียบข้อมูลสองตัวจะใช้เครื่องหมาย ===
  • ต้องการสร้าง instance แบบแชร์ ซึ่งอยู่ในสถานะที่เปลี่ยนแปลงได้ตลอดเวลา
ใน Swift นั้นไม่ว่าจะเป็น Array, String หรือ Dictionary เป็น Value Type ทั้งหมด (สำหรับใครที่ไม่รู้ Type ทั้งสามเป็น struct ไม่ใช่ class เหมือน NSArray, NSString และ NSDictionary) ซึ่งมีพฤติกรรมเหมือน int ใน C เลย instance ทุกตัวที่ถูกสร้างขึ้น จะแยกกันอย่างชัดเจน ซึ่งเราไม่ต้องทำอะไรพิเศษเพื่อป้องกันการเปลี่ยนแปลงข้อมูลใน instance โดยที่ไม่ได้ตั้งใจ และที่สำคัญ เราสามารถที่จะส่งข้อมูลระหว่าง thread ได้ โดยไม่ต้องห่วงเรื่องการทำ synchronization ซึ่งจะช่วยให้เราเขียนโค้ดที่สามารถพยากรณ์เหตุการณ์ที่จะเกิดขึ้นได้ค่อนข้างแม่นยำ

Popular posts from this blog

[Android Dev] การติดตั้ง Eclipse+AndroidSDK เพื่อพัฒนาโปรแกรมบน Android

12 วิธี การบริการและดูแลลูกค้าในร้าน Starbucks

5 TED Talk ที่จะช่วยให้คุณทำงานดีขึ้น