Objective-C 2.0 Programming : Property

ถ้าหลังจากที่ได้เขียนเกี่ยวกับ ภาษา Objective-c มาล้วนๆ และก็ได้พอขึ้น cocoa กับ iphone ไปบ้าง แต่ว่ามันก็ยังมีบางเรื่องที่ผมคิดว่า ต้องเขียนก่อน นั่นก็คือ Objective C 2.0 นั่นเอง

Objective-C 2.0 ต่างจาก Objective-C หรือเปล่า ?

คำตอบก็คือ มันก็ไม่ได้ต่างหรอกครับ เพียงแค่เค้าเพิ่มบางอย่างในตัวภาษาเข้ามา อาทิเช่น Garbage Collection อะไรแบบนี้เป็นต้น ฉนั้นแล้วก็ไม่ต้องไปกังวล ว่านี่ต้องศึกษาใหม่เลยหรือเปล่า และในวันนี้ผมจะ เริ่มด้วย คุณสมบัติใหม่ๆที่เพิ่มเข้ามาของ objective-c 2.0 ซึ่งมันจะช่วยอำนวยความสะดวกมากๆ ต่อการเขียนโปรแกรม งั้นเรามาเริ่มเลยดีกว่า

@property

เป็นคุณสมบัติที่เพิ่มเข้ามาใน objective-c 2.0 นี้ โดยปกติแล้ว เมื่อเราประกาศ member ใน class แล้วเราก็มักจะมี Function Get/Set กับตัวแปรนั้นๆเช่นว่า

ส่วนตัว source file  ก็เขียนได้ว่า

ในตัวโปรแกรมอาจจะมีการเรียกใช้ เช่น

จะเห็นว่า ยังไงเราก็ไม่สามารถเข้าไปใช้ score ได้ตรงๆ ต้องเรียกผ่าน getScore / setScore แต่ใน objective-c 2.0 นั้นเราไม่จำเป็นต้องเขียน set/get ก็ได้ โดยสิ่งที่เราจะทำก็คือ ทำให้ score นั้นเป็น property ของ class-Student ซะเลย

วิธีการก็ไม่ได้ยากเย็นอะไรนัก สิ่งที่ต้องทำก็คือ บอกว่า member นั้นเป็น property ดังตัวอย่าง code ข้างล่างนี้

ส่วนของ code เราก็เพียงแค่เขียน synthesize เข้ามา

เพียงเท่านี้ก็เรียบร้อย ส่วนวิธีการก็คือ เรียกผ่านเครื่งหมาย “.” เช่นตัวอย่างแบบนี้

จะเห็นว่ามันช่วยลดการเขียน set/get ลงไปได้เยอะเลย ลองนึกว่า หาเรามี member สัก 20 ตัวและต้องเขียน set/get นี่ก็คงต้องเขียนทั้งหมด 40 method เลยทีเดียว

Attributes

จาก  code ที่ผ่านมาจะเห็นว่า เราได้เขียน property กันไปแล้ว จะเห็นว่ามี keyword – assign อยู่ เช่น

@property (assign) int a;

keyword  เหล่านี้เป็นตัวกำหนดลักษณะของ property ต่างๆว่ามีลักษณะเช่นไร และลักษณะต่างๆ ก็แบ่งออกได้เป็น

Setter Attribute ได้แก่

  • assign
    โดยปกติแล้วจะถูกกำหนดมาให้เป็น default อยู่แล้ว
  • retain
    จะทำการ release ค่าที่เก็บไว้ก่อน แล้วหลังจากนั้นจะ retain ค่าใหม่
  • copy
    จะทำการ release ค่าที่เก็บไว้ก่อน แล้วหลัวจากนั้นจะ copy ค่าใหม่เข้ามา โดยปกตินิยมใช้กับ string

เราอาจจะไม่กำหนด attribute แต่ถ้าหากว่าเราไม่ได้ใช้งาน Garbage Collection นั้นเราต้องเลือกใช้อย่างใดอย่างหนึ่ง

Writability Attribute

  • readonly
    ถ้าหากเรากำหนดเป็นแบบนี้ ตัว compiler จะไม่สร้าง setter ให้เรา
  • readwrite

วิธีการใช้ก็คือ ใช้เครื่องหมาย “,” คั่น ระหว่าง attribute ต่างๆเช่น

@property (assign,readonly) int a;

Atomic Attribute

  • nonatomic
    โดยปกติจะเป็น atomic

แล้ว atomic กับ nonatomic ต่างกันยังไง ?
ถ้าหากเป็น atomic นั้นแต่ละ Thread จะเข้าไปเปลี่ยน ค่าใน property พร้อมๆกันไม่ได้ เพราะว่าจะทำการ Lock ค่าไว้และเมื่อเปลี่ยนแปลงค่าเสร็จเรียบร้อยแล้วถึงจะ Unlock ให้ thread อื่นเข้าไปใช้ ก็ถ้าเราใช้ nonatomic ก็จะไม่มีการ lock

@synthesize @dynamic

โดยปกติแล้วเราจะใช้ synthesize เพราะว่ามันจัดการ เขียน setter/getter ให้เรา แต่เรายังอาจจะเขียน setter/getter เองก็ได้ วิธีการก็คิือ ใช้ @dynamic แทน โดยลักษณะของ code จะเป็นประมาณนี้

ครั้งหน้ามาต่อด้วย Objective-C 2.0 อีกครั้ง

Loop Optimize

พอดีว่าผมอ่านเรื่อง Locality of reference แล้วมันน่าสนใจ มันเป็น topic เกี่ยวกับการ optimize ของ memory access ว่าเราจะเขียนโปรแกรมยังไงให้การเข้าถึง memory นั้นเร็วที่สุด ( ถ้าหากเราเข้าถึงเร็วมันก็หมายถึงว่า โปรแกรมของเราก็เร็วขึ้นด้วย ) โดยปกติแล้วในภาษา c/c++ เมื่อเราเขียนข้อมูลในลักษณะของ Array นั้นตัวเลขที่อยู่ด้านซ้ายสุดจะเป็น row ส่วนตัวต่อมาจะเป็น column และวิธีการเขียนให้เพิ่มประสิทธิภาพของเรานั้น ก็ควรจะเขียนให้มันมีการเคลื่อนที่ของตำแหน่งที่จะอ่านต่อไปในลักษณะอ่านอยู่ใน memory page เดียวกัน ดูรูปประกอบ

จากภาพ ประกอบ Memory Page นั้นจะเรียงเป็นลักษณะ เหมือนลิ้นชักที่เป็นชั้นๆ (row) มันก็เหมือนกับ เมื่อเราเปิดตู้เอกสาร ที่มีหลายๆลิ้นชัก ถ้าเราจะหาเอกสารสักชิ้น ลองคิดว่าถ้าเราหาทีละชั้น โดยหยิบออกมาทีละชิ้นจนหมดชั้นนั้นแล้วค่อยไปเริ่มชั้นใหม่ เทียบกับ เปิดออกมาหนึ่งชั้นและหยิบมาหนึ่งชั้นแล้วก็ปิด หลังจากนั้นก็เปิดชั้นต่อไปแล้วก็หยิบมาตรวจอีก 1 ชิ้นแล้วก็ไปชั้นใหม่ แบบไหนเร็วกว่า

ก็แน่นอนว่า การค้นหาทีละชั้นแล้วค่อยไปหาชั้นต่อไปนั้นเร็วกว่า การเขียนโปรแกรมก็ไม่ได้ต่างอะไร เพื่อเป็นการเห็นชัดๆ ผมมีตัวอย่าง Code ภาษา C ที่ทำการคำนวนการคูณของ Matrix

ตัวอย่าง code แรก ผมทำการคำนวนโดยที่ ตำแหน่งที่ต้องเปลี่ยนบ่อยที่สุดก็คือ k และแน่นอนว่ามันเป็นตำแหน่งของ row

และ code ที่สอง โดยผมสลับตำแหน่งของ Loop ให้ตำแหน่งที่ต้องเปลี่ยนบ่อยที่สุดคือ j และมันก็เป็น column

ก็อย่างที่ผมบอกไป ว่าถ้าเราเข้าถึงข้อมูลทีละชั้น (row) แล้วค่อยๆเลี่อนไปทีละอัน กับหา 1 อันแล้วเปลี่ยนชั้น (row ) อะไรจะ เร็วกว่า ก็ตอบแทบไม่ต้องคิดเลย นั่นก็คือ code อันที่สองมันย่อมเร็วกว่าแน่ๆ เอาละ งั้นเรามาลองทดสอบกันดูเลยดีกว่า ว่ามันจะเร็วกว่าสักเท่าไหร่กันเชียว

จาก code ข้างบน ผลลัพธ์ของ สอง Loop นี้ทำงานเหมือนกัน แต่วิธีการต่างกัน
และผลลัพธ์จากการทำงานได้แบบนี้
Loop A Total time: 23
Loop B Total time: 6

โอ้โห จะเห็นว่า มันทำงานเร็วกว่าถึง 4 เท่า !!!

แค่เปลี่ยน สลับตำแหน่ง array นิดเดียวทำงานเร็วขึ้นเป็นกอง
ก็สำหรับวันนี้ถ้าสงสัยอะไรก็ถามได้ใน Forum นะครับ

Download Source Code