iOS Tutorial – Begin with Swift ( day 6 ) – Enumerations

swift-128x128รู้จักกับ enumerations
enumeration คือประเภทของข้อมูลแบบหนึ่งที่กำหนดขึ้นเอง สำหรับจับกลุ่มของข้อมูลที่มีความเกี่ยวเนื่องกัน หากเราเคยคุ้นเคยกับภาษา c ข้อมูลประเภท enumeration จะเป็นการกำหนดชื่อของข้อมูลกับค่าที่เป็น integer แต่ใน swift สามารถทำได้มากกว่านั้น ใน swift การกำหนดค่าให้ enumeration จะแบ่งออกเป็นสองแบบใหญ่ๆ

  • raw value ค่าคงที่จะถูกกำหนดให้ตามแต่ละกรณีไปโดยจะเป็นค่าคงที่ไม่เปลี่ยนแปลงโดยจะสามารถเก็บข้อมูลได้เป็นชนิด String, Character, integer, float
  • associate value  ค่าที่จะถูกกำหนดโดยรูปแบบได้ก็ได้ ตามแต่ละกรณี เราจะมาลงรายละเอียดใน enumeration ประเภทนี้ต่อไป

วิธีการประกาศ

enumeration

 

 

 

 

เราประกาศใช้ enumeration ด้วย keyword “enum” จากนั้นตามด้วยชื่อประเภทของข้อมูลที่เราจะสร้างขึ้น<enumeration_name> ซึ่งประเภทของข้อมูลนี้ ควรจะขึ้นต้นด้วยตัวพิมพ์ใหญ่ เพราะเรากำลังจะประกาศประเภทของข้อมูลใหม่และชื่อของประเภทควรจะเป็นเอกพจน์อีกด้วย จากนั้นรายละเอียดของของมูลทั้งหมดจะอยู่ภายในเครื่องหมาย {}

ตัวอย่างการใช้ enumeration

enum Direction {
     case Left
     case Right
     case Foward
     case Backword
}

จากตัวอย่าง หากสมมติว่าเราจะเขียนเกมส์และสำหรับวัตถุใดๆ เรากำลังจะกำหนดทิศทางการเดิน เราทราบว่าเกมส์ที่เราจะเขียนทิศทางการเดินของวัตถุนั้นมีแค่ 4 ทิศเท่านั้น เราสามารถกำหนดค่าทิศทางการเดินไว้ใน enumeration ได้เพื่อจะสะดวกในการเรียกใช้ในโปรแกรม โดยทิศทาง Left, Right, Foward, Backward เรียกว่า เป็น enumeration case เราจะใช้คีย์เวิร์ด “case” เพื่อกำหนด ค่าของข้อมูลในแต่ละกรณี
ใน swift นั้น enumeration จะต่างจาก c และ objective-c ค่า default ที่ถูกกำหนดไม่ใช่ integer 0,1,2 … เสมอไป

การเรียกใช้

var directionToLeft = Direction.Left

และเมื่อมีการ กำหนดประเภทของข้อมูลให้ตัวแปรเรียบร้อยแล้ว เราสามารถทำการกำหนดค่าข้อมูลครั้งต่อไปด้วยรูปย่อ ดังนี้

directionToLeft = .Right

เราสามารถ match ค่าของ enumeration ด้วย switch-statement

directionToLeft = .Left
switch directionToLeft
    case .Left:
        print("Walk to the left")                   
    case .Right:
        print("Walk to the right")
    case .Foward:
        print("Walk foward")
    case .Backward:
        print("Walk backward")

ผลที่ได้คือ

Walk to the left

การใช้ enumeration แบบ Assosicated value

การประกาศ enumeration แบบนี้จะทำให้สามารถเก็บข้อมูลได้หลากหลายขึ้นกว่า enumeration จากภาษาทั่วไป และในแต่ละ case จะสามารถเก็บข้อมูลได้หลายหลาย ตัวอย่างเช่น หากเราต้องการทำระบบสำหรับเก็บข้อมูลบุคคลที่เข้ามาใช้ระบบของเราซึ่งอาจจะเป็นคนไทยหรือต่างชาติ แต่ละคนที่ใช้ระบบของเรา เรากำหนดให้มีการยืนยันตัวตนที่ชัดเจน กรณีสำหรับคนไทย เราจะใช้เลขประจำตัวประชาชนซึ่งมี 13 หลัก โดยแต่ละหลักนั้น เลขแต่ละตัวจะบอกความสำคัญของข้อมูลที่แต่ต่างกัน ดังนี้

1-2345-67890-12-3

  • หลักแรก ระบุประเภทของบุคคล
  • หลักที่ 2-5 เลขรหัสของสำนักทะเบียนหรืออำเภอ
  • หลักที่ 6-10 กลุ่มของบุคคลแต่ละประเภทแยกตามหลักแรก
  • หลักที่ 11-12 ลำดับที่ของแต่ละบุคคลในกลุ่มประเภทการจัดลำดับ
  • หลักที่ 13 ตัวเลขตรวจสอบความถูกต้องโดยการคำนวณจาก 12 หลักแรกโดยวิธีเลขคณิตมอดูลาร์

รายละเอียดเพิ่มเติมเกี่ยวกับเลขประตัวประชาชนอ่านได้ที่นี่

และสำหรับผู้ใช้ที่เป็นชาวต่างชาติเราจะทำการเก็บข้อมูลจากเลขพาสปอร์ต ซึ่งสามารถเก็บเป็น String ดังนี้

AA1234567

 

จากข้อมูลดังกล่าว เราสามารถกำหนดประเภทของข้อมูลใหม่ในระบบได้ดังนี้

enum UserIdentification{
    case Thai(Int, Int, Int, Int, Int)
    case Foreigner(String)
}

อ่านได้คือ ข้อมูลประเภท UserIdentification หากข้อมูลมีค่าเป็น Thai จะมีข้อมูลที่เกี่ยวข้องกันคือ กลุ่มของตัวเลข จำนวน 5 ชุด และหากข้อมูลมีค่าเป็น Foreigner จะมีข้อมูลที่เกี่ยวข้องกัน คือ String หนึ่งชุด

หากเราต้องการกำหนดข้อมูลในระบบให้ผู้ใช้ระบบซึ่งเป็นคนไทยหนึ่งคน คนต่างชาติหนึ่งคน เราสามารถประกาศได้ดังนี้

var userA = UserIdentification.Thai(1, 2345,65890, 12, 3)
var userB = UserIdentification.Foreigner("AA1234567")

เมื่อเราต้องการจะนำข้อมูลประเภทนี้ ไปใช้ต่อและต้องการดึงข้อมูลที่เกี่ยวข้องออกมาใช้ สามารถเรียกได้ดังนี้

var userA = UserIdentification.Thai(1, 2345,65890, 12, 3)
switch userA{
    case .Thai(let v1, let v2, let v3, let v4, let v5):
        print("\(v1)-\(v2)-\(v3)-\(v4)-\(v5)")                      // Result: 1-2345-65890-12-3
    case .Foreigner(let v1):
        print("\(v1)")
}

เราสามารถใส่คีย์เวิร์ด “let” หรือ “var” ไปหน้าชื่อตัวแปรที่เราต้องการอ่านออกมา จากนั้น เราสามารถนำค่าข้อมูลที่เกี่ยวข้องกับ ค่า enumeration นั้นไปใช้งานได้เลย

การใช้ enumeration แบบ raw value
เราจะเห็นว่าการใช้ enumeration แบบ associate value นั้น แต่ละครั้งที่แต่ละกรณีที่ถูกเรียกใช้ ค่าของข้อมูลจะแตกต่างกัน ขึ้นอยู่กับว่า ข้อมูลที่เกี่ยวข้องกันที่เราใส่เข้าไปในครั้งนั้นๆ เป็นอย่างไร แต่สำหรับการใช้ enumeration แบบ raw value นั้น ทุกๆครั้งที่เรียกใช้ ค่าของข้อมูลแต่ละกรณี ข้อมูลจะตายตัวสำหรับทุกๆครั้งที่เรียกใช้

ตัวอย่างการประกาศ enumeration แบบ raw value โดยกำหนดข้อมูลเอง

enum Direction:String {
    case Left = "left"
    case Right = "right"
    case Foward = "foward"
    case Backword = "backward"
}

จากข้างต้นเป็นการประกาศ enumeration ประเภท Direction ซึ่งเราประกาศไว้ว่าแต่ละกรณี เราจะเก็บค่าข้อมูลเป็น String และเรามีการกำหนดค่าตั้งต้นของข้อมูลไว้ให้แล้ว

หากเราไม่ได้กำหนดค่าตั้งต้นเข้าไป enumeration จะเซตค่าตั้งต้นให้เองตามชนิดข้อมูลที่กำหนด ถ้าเรากำหนดให้ข้อมูลเป็น integer ข้อมูลในแต่ละเคสจะเพิ่มขึ้นทีละหนึ่ง และหากไม่กำหนดค่าเริ่มต้น ข้อมูลจะเริ่มจาก 0 ไป 1,2, 3 ตามลำดับ แต่หากเป็น String ข้อมูลตั้งต้นจะเป็นไปตามชื่อของแต่ละเคสไปเลย

ตัวอย่างการประกาศ enumeration แบบ raw value โดยไม่กำหนดค่าเริ่มต้น

enum Genre:Int{
    case Pop                      // 0
    case Jazz                     // 1
    case Rock                     // 2
    case Classic                  // 3
}

จากตัวอย่างข้างต้น เรากำหนดชนิดของข้อมูลคือ Genre และกำหนดกรณีของข้อมูลให้ตามลำดับ โดยให้ค่าของข้อมูลแต่ละกรณีเป็นชนิด integer โดยไม่กำหนดค่าตั้งต้น enumeration จะกำหนดค่าตั้งต้นให้เอง โดยเริ่มจาก 0 และเพิ่มขึ้นทีละ 1ในแต่ละกรณี ดังนั้น Pop จะมีค่าข้อมูลเป็น 0 และ Jazz จะมีค่าข้อมูลเป็น 1 ตามลำดับ

enum Direction:String{
    case Left                      // Left
    case Right                     // Right
    case Foward                    // Foward
    case Backward                  // Backward
}

จากตัวอย่างข้างต้น เรากำหนดข้อมูลชนิด Direction โดยให้กรณีของข้อมูลที่เป็นไปได้คือ Left, Right, Foward, Backward และให้ค่าของข้อมูลแต่ละกรณีเป็นชนิด String โดยไม่กำหนดค่าตั้งต้น enumeration จะกำหนดค่าตั้งต้นให้เอง ตัวอย่างเช่น Left ค่าที่ได้ก็คือ Left และ Right จะได้ค่าข้อมูลเป็น Right

ตัวอย่างการดึงค่าข้อมูล enumeration  แบบ raw value

print(Genre.Rock.rawValue)      // Result: 2
print(Direction.Left)           // Result: Left

อ่านเพิ่มเติม ที่นี่