Hiding ivars from public header class in Obj-C

นานมากแล้วที่ไม่ได้ up Blog จะหนึ่งปีแล้วมั้ง วันนี้กลับมาอีก หวังว่าคงยังมีคนอ่านอยู่นะ ฮ่าๆๆ

สำหรับวันนี้จะเป็นเรื่องของภาษา Objective-C ครับผม พอดีมันเกี่ยวกับงานที่ทำ และเห็นว่า(น่าจะ)มีประโยชน์ เลยเอามาแบ่งปันกัน เพื่อไม่ให้เสียเวลา งั้นเริ่มเลยละกัน

สำหรับคนที่เขียน Objective-C มา เวลาประกาศ class เราจะต้องประกาศ ivars ลงไปใน header file ด้วย ซึ่งถ้าเราเขียนเองใช้เองก็คงจะไม่มีปัญหาอะไร แต่ถ้าเกิดว่าเราเขียน library ที่ต้องการให้คนอื่นมาใช้ต่อเนี่ย คนที่เขานำ class ของเราไปใช้ก็จะเห็นหมดเลยว่า instance ของเรามี ivar อะไรบ้าง ซึ่งบางครั้งก็ไม่เป็นผลดีนัก

หลังจากที่ลองหาข้อมูลดูสักพัก ก็พบวิธีหนึ่งในการซ่อน ivars เหล่านี้จาก public header file ครับ ซึ่งคิดว่า Apple เองก็คงใช้วิธีนี้ใน SDKs ของตนด้วย (พวก NSArray, NSSet etc.)

วิธีที่ว่าก็คือ การเอา ivars ทั้งหมด ออกจาก public header class ที่เราเปิดไว้ แล้วนำไปใส่ใน class จริงๆที่จะเป็น object จริงๆของเราแทน อ่านแล้วคงงง มาดูตัวอย่างเลยละกัน

สมมติว่าเรามี class PublicClass ซึ่งเป็น class ที่เราจะให้ผู้ใช้ library ของเราเห็น และนำไปใช้ โดยจะมี ivars เป็น NSString *string กับ NSArray *array และมี method – (void)method1 และ -(void)method2 นะครับ แต่เราจะไม่ให้ คนที่นำ class PublicClass ของเราไปเห็นว่าเรามี ivar string กับ array โดยจะเห็นแค่ว่ามี method1 และ method2 อยู่

ทีนี้ใน header file ของ PublicClass เราก็ประกาศว่ามี method ทั้ง 2 ไว้ แต่จะไม่ประกาศว่ามี ivars 2 ตัวนั้นอยู่ เพราะเราไม่อยากให้เขาเห็น แต่เราจะสร้าง class อีก class ไว้ภายใน library ของเราเอง ซึ่ง class นี้จะเป็น class จริงที่ใช้กัน พูดง่ายๆก็คือ PublicClass นั้นเป็นเหมือน dummy นั่นเอง

PublicClass.h

@interface PublicClass : NSObject
- (void)method1;
- (void)method2;
@end

PublicClass.m

@interface RealPublicClass : PublicClass {
NSString *string;
NSArray *array;
}
@end

@implementation PublicClass
+ (id)allocWithZone:(NSZone *)zone {
return NSAllocObject([RealPublicClass class], 0, zone);
}
- (void)method1 {
[self doesNotRecognizeSEL:_cmd];
}
- (void)method2 {
[self doesNotRecognizeSEL:_cmd];
}
@end

@implementation RealPublicClass
- (void)method1 {
NSLog(@”Mehtod1 called”);
}
- (void)method2 {
NSLog(@”Mehtod2 called”);
}
@end

ข้างต้น เป็นตัวอย่างของการสร้าง dummy class และ class จริง โดยเราจะให้คนที่นำ library ของเราไปใช้เห็นแค่ PublicClass.h เท่านั้น คนที่ใช้ Library ของเราจะก็ใช้​ PublicClass ไปตามปกติ แต่ว่า instance จริงๆแล้วจะเป็น RealPublicClass น่ะครับ

โคดที่น่าสนใจตรงนี้ก็คือ

+ (id)allocWithZone:(NSZone *)zone {
return NSAllocObject([RealPublicClass class], 0, zone);
}

โคดตรงนี้ก็ไม่มีอะไรมาก อธิบายง่ายๆก็คือ ถ้าเกิดมีใครก็ตามต้องการจะสร้าง instance ของ PublicClass นั้น เราจะสร้าง instance ของ RealPublicClass ให้แทน ส่วนโคดใน method1 และ method2 ของ PublicClass นั้นมีไว้ในกรณีที่เขาสร้าง instance ของ PublicClass ด้วยวิธีไหนก็ตาม และเราไม่ต้องการให้เขาใช้งานได้จริงๆ เราก็จะทำให้ PublicClass instance มันไม่รับ msg ของ method ทั้ง 2 ครับผม

post นี้ขอจบเพียงเท่านี้ละกับ หวังว่าจะเป็นประโยชน์แก่ผู้อ่าน ไม่มากก็น้อยนะครับ :)

No TweetBacks yet. (Be the first to Tweet this post)
This entry was posted in Post. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>