Home > Objective-C > [Objective-C myNote] ภาคต่อ 1

[Objective-C myNote] ภาคต่อ 1

หายไปนานแสนนานไม่ได้เข้ามา update เลย นานที่ว่าหน่วยไม่ใช่เป็นเดือนนะครับ หน่วยเป็นปี ฮะ ฮะ สำหรับ Note ที่ทิ้งค้างไว้ ก็จะมาต่อกันให้จบในคราวนี้แหละครับ สำหรับคราวที่แล้วนั้นมาจบตรงที่  การออกแบบ class interface – Designing a Class interface 

เริ่มที่ หัวข้อนี้ใหม่เลย ครับ

การออกแบบ class interface – Designing a Class interface

การสร้าง class มี 2 ส่วนคือ

  • Class interface  เก็บไว้ใน  ClassName.h
    • Define instance variable and public methods
  • Implementation เก็บไว้ใน ClassName.m
    • Actual code
    • Private method ซึ่ง ใช้ภายใน
ตัวอย่าง class ชื่อ photo
#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
     NSString* caption;
     NSString* photographer;
 }
 @end

–    ใช้ #import directive เพื่อบอก compiler ว่าจะเรียกใช้ library อะไร
–    @interface บอกว่าเป็นการ ประกาศ class ชื่อ photo   colon บอกว่า photo มี superclass เป็นอะไร
–    ใน curly bracket ประกาศ variable 2 ตัว ชื่อ caption, photographer ซึ่งเป็น NSString
–    จบด้วย @end

ลองมาเพิ่ม  getter ให้กับ instance variable กันครับ

#import <Cocoa/Cocoa.h>
@interface Photo : NSObject {
  NSString* caption;
  NSString* photographer;
}
  caption;
  photographer;
@end;

จำได้ไหม ครับว่าโดยการปฏิบัติทั่วไปแล้ว method ของ Objective-C นั้นจะไม่ใส่ส่วนนำ หรือ prefix “get” single dash “-” นำหน้าชื่อของ method นั้นหมายถึง ชื่อนั้นเป็น instance method ส่วนเครื่องหมาย “+” หรือ plus นำหน้่า method ก็หมยถึง ชื่อนั้นเป็น class method
lass method หมายถึง class ที่สามารถถูกเรียกใช้ได้ในขณะที่ไม่ได้เป็น object หรือ class method ก็คือ static method
สมมุติ เรามี class ชื่อว่า MathFunc ดังนี้

@interface MathFunc : Nsobject
{
}
 +(int) square:(int)num;
@end

@implementation MathFunc
 +(int) square: (int)num
 {
	return num*num;
 }
@end

ดังนั้นการเรียกใช้จะเป็นดังตัวอย่างครับ โดยที่เราไม่ต้องมีการ instantiate ให้เป็น object เราก็สามารถเรียกใช้ฟังก์ชันได้ ( นี่เป็นการแสดงความหมายและการใช้งาน class method )

   value = [[square alloc]   num:5] ;

โดย default แล้ว compiler จะกำหนดชนิดของค่าที่ส่งกลับหรือค่าที่ return ของ method ใน Objective-C ให้เป็น ชนิด id จาก code ข้างบนการประกาศ method แบบนั้นในทางเทคนิคแล้วถูกต้องไม่ผิดอะไรแต่มันดูไม่ค่อยปกติ เราควรจะกำหนดชนิดของค่า return ให้เจาะจงไปเลยว่าเป็นชนิดใดดังนี้

#import 
@interface Photo : NSObject{
	NSString* caption;
	NSString* photographer;
}
-(NSString*) caption;
-(NSString*) photographer;
@end;

ลองมาเพิ่ม getter ให้กับ instance variable กันครับ

#import 
@interface Photo : NSObject{
	NSString * caption;
	NSString * photographer;
}
-(NSString*) caption;
-(NSString*) photographer;

-(void) setCaption: (NSString*)input;
-(void) setPhotographer:(NSString*)input;

@end

setter ไม่มีการ return ค่า เราจึงกำหนดด้วย void เหมือนภาษา C

การ Implement class (Class implementation)
มาทำการ Implementation โดยเริ่มที่ getter กันครับ

#import “Photo.h”

@implementation Photo 
-(NSString*) caption{
	return caption;
}

-(NSString*) photographer{
	return photographer;
}
@end 

ในส่วนของการ implementation นั้น กำหนดด้วย @implementation ตามด้วยชื่อ class ลงท้ายด้วย @end ลักษณะการเขียนเหมือนกับ interface method ที่ต้องการ implement ทั้งหมดจะต้องอยู่ระหว่าง 2 statement นี้นะครับ ส่วนของ getter นั้น ก็จะค่อนข้างคุ้น และง่ายต่อการเขียน
ต่อไปดูที่ setter ซึ่งเป็นส่วนที่จะต้องอธิบายเพิ่มเติมจาก code ที่แสดงให้ดู ดังนี้

-(void) setCaption: (NSString*)input
{
	[ccaption autorelease];
	caption = [input retain];
} 

-(void) setPhotographer:(NSString*) input
{
	[photographer autorelease];
	photographer = [input retain];
}

setter แต่ละตัวจะเห็นว่าต้องเกี่ยวข้องกับตัวแปร สองตัว ตัวแรกคือ ตัวที่อ้างอิงไปที่ ตัวแปรของ object เอง เช่น caption ส่วนตัวแปรที่ สองเป็น input ใน environment ที่เป็น garbage collected เราสามารถกำหนดค่าใหม่ได้โดยตรง เช่น

-(void) setCaption:(NSString*) input{
	caption = input;
}

แต่ถ้่หากเราไม่สามารถใช้ garbage collection ได้เราต้องทำการ release ค่าเก่า แล้วกำหนดค่าใหม่ให้ด้วย เครื่องหมาย autorelease และ retain ตามตัวอย่างครับ
การ ปล่อย หรือ free ข้อมูลการอ้างอิง (reference) ไปยัง object นั้นมี 2 วิธีคือ release และ autorelease
สำหรับ release นั้นจะทำการกำจัด reference ทันที ส่วน autorelease นั้นจะทำการกำจัดหลังจาก ระยะเวลาหนึ่ง และจะต้องหลังจากที่ function นั้นจบลงแล้วด้วย นอกจากจะมีการเปลี่ยนแปลงเพิ่มเติม
** autorelease method ใช้กับ setter ดูจะปลอดภัยกว่าเพราะว่าตัวแปรสำหรับค่าเก่าและค่าใหม่นั้นสามารถชี้ไปยัง object เดียวกันได้ หรือ ที่ตำแหน่งเดียวกันเราไม่จำเป็นต้องทำการ release object ที่เราต้องการ retain ค่า ทันทีทันใดก็ได้
ครับดูจะสบสน ในตอนนี้ แต่หลังจากผ่านไปสักระยะหนึ่งก็จะพอเข้าใจขึ้นนะครับ เราไม่จำเป็นต้องเข้าใจทุกสิ่งอย่างทั้งหมดในตอนนี้

Init
เราสามารถ ใช้ Init method สำหรับการกำหนดค่า เริ่มต้นให้กับตัวแปร instance ได้

-(id) init 
{
	if( self = [super init])
	{
		[self setCaption:@”Default caption”];
		[self setPhotographer:@”Default Photographer”];
	}
	return self;
}

code ค่อนข้างจะอธิบายการทำงานได้ดีอยู่แล้ว ยกเว้นในส่วนของ if( self=[super init]) ซึ่งมีลักษณะการใช้เหมือนการ assign ค่า [super init] ให้กับ self ในความรู้สึกมันแปลก ๆ
อธิบายได้ว่า เป็นการร้องขอให้ superclass ทำการ initialization ตัวเอง ส่วน if statement นั้นจะตรวจสอบว่าการ initialization นั้นสำเร็จหรือไม่ก่อนการ กำหนดค่าให้กับ self

Dealloc
Dealloc method นี้จะถูกเรียกเมื่อ object กำลังถูก remove จาก memory ซึ่งเป็นการดีที่จะทำการปล่อย reference ต่าง ๆ ที่อ้าอิงอยู่ออกไปด้วย

-(void) dealloc
{
	;
	[photographer release];
	[super dealloc];
}

สองบรรทัดแรกนั้นเป็นการปล่อยหน่วยความจำในส่วนของ instance variable เราไม่ใช้การ autorelease ใช้ release จะเร็วกว่า

บบรทัดสุดท้ายนั้นสำคัญมาก เราจะต้องทำการ ร้องขอไปยัง superclass ให้ทำการปล่อยหน่วยความจำในส่วนของตัวเองด้วย หากเราไม่ทำขั้นตอนนี้ object จะไม่ถูกกำจัด ทำให้เกิด memory leak.

Dealloc method นั้นจะไม่ถูกเรียกให้ทำงานหาก garbage collection ทำงาน เราจะทำ finalizeแทน ครับในส่วนของการจัดการ memory นั้นจะขอเพิ่มเติมในรายละเอียดภายหลัง

การบริหารจัดการกับ memory เบื้องต้น [ Basic Memory Management ]
ถ้าหากเรากำลังพัฒนา application บน MAC OS X เราสามารถที่จะเลือกให้ garbage collection ทำงานได้ หมายความว่า จะทำให้เราไม่ต้องมาคำนึงถึงเรื่องการจัดการ memory จนกว่าเราจะเข้าสู่การเขียนแบบที่ซับซ้อนขึ้น เรามาเรียนรู้กันสักนิดหนึ่งนะครับ
ตั้งแต่นี้ไป สำคัญนะครับ

หากเราสร้าง object แบบใช้ alloc เราต้องทำการ release object นั้นหลังจากที่ใช้งานเสร็จแล้ว และสิ่งที่สำคัณอีกอย่างหนึ่งก็คือจะต้องไม่ ไป release object ที่ ถูกกำหนดเป็น autorelease object เพราะว่าจะทำให้ application นั้นล่มเอาง่าย ๆ

// string1 will be release automatically
NSString * string1 = [NSString string];

// must release this when done
NSString * string2 = [[NSString alloc] init];
[string2 release]

สำหรับ tutorial นี้ให้จำไว้ว่า object แบบ autorelease นั้นจะถูกกำจัดเมื่อจบ funciton นั้น

มีหลายสิ่งที่เราต้องเรียนรู้เกี่ยวกับการจัดการ memory ซึ่ง ความเข้าใจจะมากขึ้นเมื่อเราได้เรียนรู้หรือเข้าใจ concept เพิ่มเติมจากนี้

จบลงตรงนี้ก่อนนะครับ ค่อยต่อกันตอนต่อไปนะครับ
s_teerapong2000@yahoo.com

Categories: Objective-C
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: