AnyObject and Swift Type Casting


การเปลี่ยนชนิดของตัวแปรใดๆ เป็นอะไรที่มึนมาก ตอนที่ผมเขียน Swift ในตอนแรกๆ เนื่องจากชินกับการทำ Type Casting แบบก่อนๆ ที่ต้องใส่ Type ที่เราต้องการแปลงวงเล็บไว้ข้างหน้าตัวแปรที่ต้องการ เรียกได้ว่าเป็นท่ามาตรฐานเลย เช่นแบบนี้


คราวนี้บน Swift ก็มีการทำ Type Casting หลายๆ แบบด้วยกัน เริ่มจากอะไรง่ายๆ กันก่อน

Type Casting with -init method

การทำ Type Casting ด้วยวิธีนี้ จะใช้กับพวก Primitive Struct ที่มีให้บน Swift เช่นระบบตัวเลขทั้งหลาย Int, Double หรือระบบตัวเลขใน Core Graphics Framework อย่างเช่น CGFloat


AnyObject 

มีบ้างไหมเวลาที่เราไม่รู้ว่าชนิดของตัวแปรที่ได้มาเป็นชนิดอะไร ใน Objective-C จะใช้ id แต่ใน Swift จะใช้ชนิดตัวแปรพิเศษที่มีชื่อว่า AnyObject (จริงๆ แล้วเป็น Protocol) แม้ Swift จะประกาศตัวเองเป็น Strong Type Language ที่มี Type Inference Feature ก็ตาม แต่ที่ต้องมีเนื่องจากต้องทำงานร่วมกับโค้ดของ Objective-C นั่นเอง

อย่างเช่นว่า มีหลายๆ อย่างที่เราไม่รู้ว่าข้างในมันจะเป็นอะไรจนกว่าจะถึงเวลา Runtime เช่น View Controller ปลายทางของเส้นเชื่อม Segue (var destinationViewController: AnyObject) หรือของที่อยู่บน Toolbar (var toolbarItems: [AnyObject]) ซึ่งอาจจะเป็น UIBarButtonItem, UIButton, UISegmentedControl และอื่นๆ ซึ่งอาจจะผสมกันระหว่าง Object หลายๆ อย่างก็ได้


หรืออีกตัวอย่างคือมาเป็น Argument ของฟังก์ชั่นต่างๆ เช่น


หรือจะเป็นค่าที่ส่งออกจากฟังก์ชั่นแบบนี้


แล้วเวลาเราจะใช้ค่าพวกนี้ เราจะไม่มีสามารถเข้าถึง method หรือ property ของ Object พวกนั้นได้ แน่นอนล่ะ เนื่องจากเราไม่รู้ว่ามันคืออะไรใช่ไหม ดังนั้นเราต้องเปลี่ยนแปลงชนิดของมันให้เป็นชนิดที่เรา "รู้" แน่นอนว่ามันจะต้องเป็นแบบนี้ หรือเปลี่ยนแปลงชนิดให้เป็นชนิดที่เรา "คาดหวัง" ให้มันเป็น ซึ่งเราจะใช้ Keyword ใน Swift นั่นคือ "as"

Type Casting with "as"

ในกรณีที่เรามั่นใจแล้วว่ามันจะต้องเป็นไอนี่แน่ๆ เราก็ประกาศตัวแปรมารับ
และทำ Type Casting และทำสิ่งที่อยากทำได้เลย เช่นตัวอย่างโค้ดนี้


เนื่องจากเรารู้แน่นอนว่า View Controller ปลายทางเราเป็นอะไร เลยทำให้ใช้แบบนี้ได้เลย
แน่นอนว่าแอปจะแครชทันที ถ้าสิ่งที่เราพยายามเปลี่ยนให้มันเป็น ไม่ใช่สิ่งที่มันเป็น #ความรักก็เช่นกัน

แล้วถ้าในกรณีที่เราไม่แน่ใจหรือป้องกันการแครชล่ะ เราจะต้องใช้ "as?" ซึ่งจะให้เป็นการนำ Optional มาครอบสิ่งที่เราจะแปลงไว้ และใช้คู่กับ keyword "if let" เพื่อจัดการ มักจะต้องใช้ในกรณี เช็คให้มันผ่านๆ ไป และใช้มันโดยไม่ต้องการแปลง เช่น Object ที่จะได้กลับมาจาก key ตัวนี้เป็น String หรือไม่ ถ้าใช่ก็ให้ตัวแปรที่ต้องการชี้ไปหาได้เลย (Assignment Statement) หรือตามตัวอย่างนี้


Type Checking with "is"


นอกจากในการใช้เบื้องต้นแบบด้านบน ยังมีวิธีการใช้ที่น่าสนใจอย่างการแปลงค่าแบบ On the fly


และการใช้กับตัวแปรที่เป็น Container (หรือ Collection) ได้ด้วย เช่น ถ้าเราต้องการเช็คว่า Toolbar Item แต่ละตัวมีเป็นตัวแปรชนิดใด ก่อนที่จะนำไปใช้งาน เราอาจจะทำได้แบบนี้


แต่ในกรณีที่เรามั่นใจว่าในนั้นมีของแบบเดียวกันหมด เราสามารถที่จะย่อแบบนี้ได้เลย


แต่ไม่สามารถใช้ "as?" ในกรณีนี้ได้ เนื่องจากมีโอกาสเกิดคำสั่ง "for item in nil" 

Popular posts from this blog

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

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

"อีสุกอีใส" ประสบการณ์เมื่อต้องมาเป็นตอนอายุ 22