วันอาทิตย์ที่ 9 ตุลาคม พ.ศ. 2554

ภาษาอ็อบเจกทีฟ-ซี [Objective-C]

ภาษาอ็อบเจกทีฟ-ซี (อังกฤษ: Objective-C หรือ ObjC) เป็นภาษาโปรแกรมเชิงวัตถุและมีสมบัติการสะท้อน โดยแรกเริ่ม ภาษาอ็อบเจกทีฟ-ซี พัฒนาขึ้นจากภาษาซีโดยยังคงคุณลักษณะของภาษาซีไว้ครบทุกประการเพียงแต่เพิ่มระบบส่งข้อความ (messaging) แบบเดียวกับภาษาสมอลล์ทอล์กเข้าไปเท่านั้น (Objective-C runtime) ปัจจุบันภาษาอ็อบเจกทีฟ-ซีมีคุณสมบัติอื่นๆเพิ่มเติมจากการพัฒนาภาษาอ็อบเจกทีฟ-ซี 2.0 โดยบริษัทแอปเปิล

ปัจจุบันภาษาอ็อบเจกทีฟ-ซีถูกใช้มากใน Cocoa (API) ใน Mac OS X, GNUstep (API) และ Cocotron (API) เป็นต้น ซึ่งระบบเหล่านี้ได้รับการพัฒนาขึ้นโดยมีพื้นฐานจากมาตรฐาน OpenStep (API) ใน Nextstep (Operating system) โดยมีภาษาภาษาอ็อบเจกทีฟ-ซีเป็นภาษาหลัก ปัจจุบัน Mac OS Xใช้ Cocoa เป็นเฟรมเวิร์กสำหรับสร้างโปรแกรมประยุกต์ โดย ไลบรารีและ/หรือ API เหล่านี้เป็นเพียงส่วนเพิ่มขยาย (Software extension) เท่านั้น โปรแกรมที่ใช้ภาษาอ็อบเจกทีฟ-ซีทั่วไปที่ไม่ได้ใช้ส่วนเพิ่มขยายเหล่านี้ก็ยังสามารถคอมไพล์ได้ เช่นอาจใช้แต่ gcc ซึ่งรองรับภาษาอ็อบเจกทีฟ-ซี


ประวัติ

ในช่วงต้นของปี 1980s วิศกรรมซอฟต์แวร์นิยมออกแบบโปรแกรมแบบโครงสร้าง เรานิยามการออกแบบโปรแกรมแบบโครงสร้างขึ้นเพื่อแยกย่อยโปรแกรมขนาดใหญ่ลงเป็นส่วนเล็กๆ เพื่อให้ง่ายต่อการจัดการเมื่อโปรแกรมมีขนาดใหญ่ขึ้น อย่างไรก็ดี โปรแกรมแบบโครงสร้างก็มีประโยชน์น้อยลงเมื่อขนาดของปัญหาใหญ่ขึ้น เพราะต้องเขียน procedure จำนวนมากเพื่อรองรับปัญหาที่ใหญ่ขึ้น และทำให้รหัสคำสั่งมีความซับซ้อนและยุ่งเหยิง

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

ในต้นยุค 80 Brad Cox และ Tom Love ได้ให้พัฒนาภาษาอ็อบเจ็กทีฟ-ซีขึ้นที่บริษัท Stepstone ของพวกเขา โดยพวกเขาได้เรียนรู้ภาษาสมอลล์ทอล์กจาก Programming Technology Center ของบริษัท ITT Corporation ในปีค.ศ. 1981 Cox ให้ความสนใจกับปัญหาเรื่องการนำรหัสมาใช้ซ้ำ (reusability) ในกระบวนการวิศวกรรมซอฟต์แวร์ เขาคิดว่าภาษาสมอลล์ทอล์กไม่เหมาะจะใช้พัฒนา development environment สำหรับนักพัฒนาซอฟต์แวร์ระบบที่ ITT Cox เริ่มแก้ไขคอมไพเลอร์ภาษาซี โดยเพิ่มความสามารถด้านการจัดการเชิงวัตถุของภาษาสมอลล์ทอล์กเข้าไป โดยเขาเรียกมันว่า "OOPC" หมายถึง Object-Oriented Programming in C ในขณะนั้น Love ซึ่งทำงานให้กับ Schlumberger Research ในปี 1982 ก็ได้มีโอกาสใช้งาน Smalltalk-80 ซอฟต์แวร์ซึ่งส่งอิทธิพลต่อการพัฒนาภาษาอ็อบเจกทีฟ-ซีในเวลาต่อมา

และเพื่อแสดงประสิทธิภาพ Cox ได้แสดงให้เห็นว่าการปรับปรุงเครื่องมือที่มีอยู่แล้วเพียงเล็กน้อยก็สามารถทำ software component ให้ปรับเปลี่ยนได้ง่ายๆ โดยการทำ object ให้ยืดหยุ่นและสนับสนุนด้วยชุดไลบรารีซึ่งประกอบด้วยรหัสและรีซอร์ส ที่รวมกันอยู่ในรูปแบบที่สามารถนำไปใช้ข้าม platform ได้

Cox และ Love ได้ก่อตั้ง Productivity Products International (PPI) เพื่อขายคอมไพเลอร์ภาษาอ็อบเจกทีฟ-ซีและคลาสไลบรารีในเวลาต่อมา

ในปีค.ศ. 1986 Cox ได้ตีพิมพ์หนังสือที่อธิบายถึงภาษาอ็อบเจกทีฟ-ซีชื่อ Object-Oriented Programming, An Evolutionary Approach ซึ่งแม้ว่า Cox จะได้พยายามชี้ให้ว่าปัญหาหลักคือการนำรหัสมาใช้ซ้ำ (reusability) มากกว่าจะเป็นการแก้ปัญหาด้วยภาษา แต่กระนั้น Objective-C ก็ยังถูกนำไปเรียบเทียบแบบฟีเจอร์ต่อฟีเจอร์กับภาษาอื่นๆอยู่ดี

แพร่หลายเพราะ NeXT

ในปีค.ศ. 1988 บริษัท NeXT ซึ่งตั้งขึ้นโดย Steve Jobs ได้ลิขสิทธิ์จาก StepStone (เจ้าของเครื่องหมายการค้าภาษาอ็อบเจกทีฟ-ซีในขณะนั้น) โดยได้พัฒนาคอมไพเลอร์ภาษาอ็อบเจกทีฟ-ซีและชุดไลบรารี ของตัวเองโดยนำมาใช้พัฒนาระบบติดต่อผู้ใช้และระบบพัฒนาซอฟต์แวร์ชื่อ NEXTSTEP ถึงแม้ว่าเครื่อง NeXT จะขายไม่ดี แต่เครื่องมือพัฒนาของมันกลับได้รับความนิยมพอสมควร และในที่สุด NeXT ก็เลิกขายฮาร์ดแวร์ และหันมาขายซอฟต์แวร์แทน ภายใต้ชื่อ NeXTstep และ OpenStep

โครงการกนู ได้พัฒนาระบบพัฒนาซอฟต์แวร์หนึ่งตามมาตรฐาน OpenStep ในรูปแบบซอฟต์แวร์เสรี โดย Dennis Glatting ได้พัฒนา gnu-objc runtime ตัวหนึ่งขึ้นในปี 1992 โดย Richard Stallman ได้เขียนอีกตัวขึ้นแทนในเวลาไล่เลี่ยกัน ส่วน GNU Objective-C runtime ตัวที่ถูกใช้งานตั้งแต่ 1993 พัฒนาโดย Kresten Krab Thorup เมื่อเขาเป็นนักเรียนมหาวิทยาลัยในเดนมาร์ค

หลังจากที่ซื้อกิจการของ NeXT ในปี 1996 Apple ได้ใช้ OpenStep ในระบบปฏิบัติการของตนเองหรือ Mac OS X โดยได้รวมเอาภาษาอ็อบเจกทีฟ-ซีและระบบพัฒนาซอฟต์แวร์จาก NeXT ชื่อ Project Builder ซึ่งถูกแทนที่โดย Xcode ในเวลาต่อมา รวมถึงระบบออกแบบระบบการติดต่อผู้ใช้แบบ object ชื่อ Interface Builder และ Apple เรียกไลบรารีซึ่งพัฒนาต่อจาก OpenStep ว่า Cocoa

Syntax

ภาษาอ็อบเจกทีฟ-ซี [1]เป็นชั้นบางๆ บน C และเป็น สตริกต์ superset ของ C ดังนั้นคอมไพเลอร์ภาษาอ็อบเจกทีฟ-ซีจึงสามารถคอมไพล์โปรแกรมภาษา C ใดๆ ก็ได้ ภาษาอ็อบเจกทีฟ-ซี ได้รับรูปแบบการเขียนมาจากภาษาซีและภาษาสมอลล์ทอล์ก โดยรูปแบบส่วนใหญ่ (preprocessing, expressions, การประกาศฟังค์ชัน และการเรียกฟังค์ชัน) มาจากภาษาซี ขณะที่ส่วนที่เป็นการจัดการเชิงวัตถุมาจากสมอลทอล์ค

Messages

ภาษาอ็อบเจกทีฟ-ซีได้เพิ่มเติมรูปแบบการเขียนโปรแกรม เพื่อรองรับการออกแบบโปรแกรมเชิงวัตถุ โดยจะใช้การส่ง message ไปยัง object ต่างๆเช่นเดียวกับสมอลทอล์ค ซึ่งแตกต่างจากภาษาในตระกูล Simula (เช่น C++) ข้อแตกต่างมีมีความสำคัญ เพราะภาษาอ็อบเจกทีฟ-ซีจะไม่เรียก method แต่จะส่ง message

ในภาษาอ็อบเจกทีฟ-ซี ถ้ามี object หนึ่งชื่อ obj โดย class มี method ชื่อ doSomething หมายความว่า obj respond หรือตอบสนองต่อ message doSomething และถ้าเราต้องการจะส่ง message doSomething ไปยัง obj เราจะเขียนคำสั่งดังนี้

[obj doSomething];

ขณะที่ถ้าเป็น C++ เราจะเขียนว่า

obj.doSomething () ;


Forwarding

ในภาษาอ็อบเจกทีฟ-ซีจะยอมให้มีการส่ง message ไปยัง object ใดๆ แม้ว่าจะไม่มีการเตรียม method เอาไว้รองรับ (คือไม่ respond) ต่างจากภาษาอื่นๆ เช่น C++ หรือ Java ที่การเรียกใช้ method ต้องมีการระบุไว้ล่วงหน้า หาก object ได้รับ message ที่ไม่รู้จัก object จะผ่านต่อ message ที่ได้รับไปยัง method เหล่านี้

- (retval_t) forward:(SEL) sel :(arglist_t) args; // with GCC
- (id) forward:(SEL) sel :(marg_list) args; // with NeXT/Apple systems

method เหล่านี้อาจแตกต่างกันไปตามชนิดของ runtime และมักนิยมผ่านต่อไปยัง method อื่นๆในระดับของ framework เช่น forwardInvocation: ใน OpenStep

อินเตอร์เฟซ และ อิมพลีเมนเทชัน

ในภาษาอ็อบเจกทีฟ-ซี ส่วนอินเตอร์เฟซ (@interface) และอิมพลีเมนเทชัน (@implementation) จะถูกแยกออกจากกัน ในทางปฏิบัติ เรามักเก็บส่วนอินเตอร์เฟซไว้ในแฟ้ม .h และส่วนอิมพลีเมนเทชันใน .m
 
@interface

เรามักนิยามส่วนอินเตอร์เฟซของคลาสในแฟ้ม .h โดยทั่วไปเรามักตั้งชื่อแฟ้มนี้ให้ตรงหรือสอดคล้องกับชื่อของคลาส เช่นถ้าคลาสเราชื่อ Thing เราก็มักจะประกาศอินเตอร์เฟซของคลาส Thing ในแฟ้ม Thing.h

รูปแบบของการประกาศอินเตอร์เฟซมีลักษณะดังนี้:

@interface classname : superclass name
{
    instance variables
}
+ classMethod1;
+(return_type) classMethod2;
+(return_type) classMethod3: (param1_type) parameter_varName;
 
-(return_type) instanceMethod1: (param1_type) param1_varName : (param2_type) param2_varName;
-(return_type) instanceMethod2WithParameter: (param1_type) param1_varName andOtherParameter: (param2_type) param2_varName;
@end

method แบบ instance จะถูกนำหน้าด้วยเครื่องหมายลบ "-" ส่วน method แบบ class จะถูกนำหน้าโดยเครื่องหมายบวก "+" ตรงนี้จะแตกต่างจาก UML diagrams ซึ่งใช้ในแสดงว่า method เป็นแบบ private หรือ public

ค่าที่ถูก return จาก method มีลักษณะเช่นเดียวกับในภาษาซี เช่น void, int, ฯลฯ โดยจะมีการประกาศ type ชื่อ id ไว้แทน instance อ็อบเจกอะไรก็ได้

เราประกาศพารามิเตอร์ของ method ด้วยเครื่องหมายทวิภาคหรือโคลอน ":" ตามด้วย type ของพารามิเตอร์ในวงเล็บ แล้วตามด้วยชื่อของพารามิเตอร์ เรามักใส่ชื่อที่มีความสอดคล้องกับพารามิเตอร์หน้าเครื่องหมายทวิภาค เพื่อบอกว่าพารามิเตอร์แต่ละตัวมีบทบาทอย่างไร

-(void) setRange: (int) start : (int) end;
-(void) importDocumentWithName: (NSString *) name withSpecifiedPreferences: (Preferences *) prefs beforePage: (int) insertPage;

@implementation

ส่วนอินเตอร์เฟซจะประกาศแต่ต้นแบบของ method เท่านั้น โดยไม่รวมถึงการกำหนดว่า method นั้นจะต้องทำอะไรบ้าง การกำหนดว่า method นั้นจะต้องทำอะไรจะทำในส่วนอิมพลีเมนเทชัน ตามปรกติ ส่วนอิมพลีเมนเทชันจะอยู่ในไฟล์นามสกุล .m ตัวอย่างเช่น Thing.m ที่มีการกำหนดส่วนอิมพลีเมนเทชันไว้ดังนี้

@implementation classname
+ classMethod
{
    // implementation
}
 
- instanceMethod
{
    // implementation
}
@end

method มีหน้าตาแตกต่างจากฟังค์ชันในภาษา C เช่นถ้าในภาษาซีเป็นอย่างนี้

int do_something (int i)
{
    return square_root (i) ;
}

โดยมี int do_something (int) เป็นต้นแบบ

เมื่อมาประกาศเป็น method ในภาษาอ็อบเจ็กทีฟ-ซี จะมีหน้าตาอย่างนี้

- (int) do_something: (int) i
{
    return [self square_root: i];
}

ถ้าให้ถูกธรรมเนียมเราจะกำหนดชื่อ method ข้างต้นใหม่ โดยเราจะตั้งชื่อ method ให้สอดคล้องกับ argument ตัวแรกดังนี้

- (int) doSomethingWithInt: (int) i
{
    return [self squareRootOfInt:i];
}

แม้ว่าอาจจะดูยุ่งยากแต่ก็ช่วยให้เราจำ argument ได้ง่ายขึ้น ตัวอย่างเช่น

- (int) changeColorWithRed: (int) r  green: (int) g  blue: (int) b

โดยเราจะเรียก method แบบนี้:

[myColor changeColorWithRed:5 green:2 blue:6];

คอมไพเลอร์ภาษาอ็อพเจ็กทีฟ-ซีแต่ละตัวก็จะกำหนดชื่อ method เป็นการภายในแตกต่างกันไป เช่นถ้า method -changeColorWithRed:green:blue: เป็น method แบบ instance ของ class Color คอมไพเลอร์ก็อาจจำ method นี้ในชื่อ _i_Color_changeColorWithRed_green_blue เป็นต้น โดยตัว i จะบอกว่าจุดนี้คืออิมพลีเมนเทชัน method แบบ instance และตามด้วยชื่อคลาสและชื่อ method และมีการเปลี่ยนเครื่องหมาย : เป็น _ ดังนี้แล้ว เมื่อพารามิเตอร์เป็นส่วนหนึ่งของชื่อ method ลำดับของพารามิเตอร์ในภาษาอ็อบเจ็กทีฟ-ซีจึงสลับที่กันไม่ได้

อย่างไรก็ตาม เราแทบไม่ได้ใช้ชื่อภายในของฟังชั่นโดยตรง โดยทั่วไป การส่ง message จะถูกเปลี่ยนให้อยู่ในรูปแบบของการเรียกฟังค์ชั่นที่กำหนดไว้ในไลบราลีส่วน run-time และปรกติเวลาเราส่ง message เราก็จะไม่คำนึงถึง class ที่แท้จริงของส่วน receiver (myColor) อยู่แล้ว นั่นคือการจัดการหา method จะเป็นหน้าที่ของ run-time

Objective-C 2.0

เป็นส่วนเพิ่มเติม syntax จากภาษา Objective-C โดยบริษัท Apple เป็นผู้พัฒนาเพิ่ม เช่น

    Garbage collection (computer science) (ทั้งนี้ ใน Objective-C runtime ของ GNU สามารถใช้งาน Boehm-Demers-Weiser conservative garbage collector ได้ก่อนหน้า Objective-C 2.0 แล้ว)
    Properties (@property) ช่วยจัดการการประกาศ instance variable
    Fast enumeration การเพิ่มประสิทธิภาพในส่วน runtime

for (int i=0; i<[thePeople count]; i++) {
    Person *p = [thePeople objectAtIndex:i];
    NSLog (@"%@ is %i years old.", [p getName], [p getAge]) ;
}
 
for (Person *p in thePeople)
    NSLog (@"%@ is %i years old.", [p getName], [p getAge]) ;

Objective-C++

เป็นส่วนเพิ่มภาษาที่ช่วยให้รวม code Objective-C และ C++ เข้าด้วยกันง่ายขึ้น

คอมไพเลอร์

gcc
clang (llv)
POC มีจุดเด่นเช่นการรองรับ block แบบ smalltalk

ที่มา http://th.wikipedia.org