สำหรับโปรแกรมแรกที่จะได้ลองเขียน ผมใช้ชื่อว่า WordCount เป็นโปรแกรมง่ายๆ เอาไว้นับตัวอักษรใน text field ( ถ้าเป็น windows จะเรียกว่า text box ) แล้วก็แสดงผลออกมา

New Project
ก่อนอื่นเลยเราก็เปิดโปรแกรม xcode ขึ้นมาครับ แล้วเราก็สร้าง project ด้วย Cocoa Application หน้าตาจะเป็นประมาณนี้

New Cocoa Application Project


เมื่อเราเลือกโปรเจคเรียบร้อย และทำการตั้งชื่อว่า WordCount แล้วเราก็จะเห็น หน้าต่างมีหน้าตาประมาณนี้

ก็เท่านี้ก็เป็นการได้สร้าง Cocoa Application Project เรียบร้อยแล้ว

โดยปกติแล้วเมื่อเราสร้าง Cocoa Application ขึ้นมาจะมี File ทั้งหมดประมาณ 5 File ด้วยกัน แต่จะมี File ที่สำคัญ อยู่ด้วยกัน 3 File นั่นก็คือ

  • main.m ถ้าเราเปิด file นี้มาดูจะเห็น code ตามข้างล่าง

int main (int argc, char* argv)
{
return NSApplicationMain (argc, (const char**) argv);
}

กว่า 95 % เราแทบจะไม่ต้องไปแก้ไข file นี้เลย

  • MainMenu.xib เป็น File ที่เก็บ interface ของโปรแกรม
  • info.plist ย่อมาจาก property list เป็น file ที่เก็บค่ารายละเอียดต่างๆ

Let’s make interface

ต่อไปก็เป็นการออกแบบหน้าตาโปรแกรม การออกแบบ user interface นั้นทำได้ง่ายมากๆเพียงแค่เราเปิด file ที่มีชื่อว่า MainMenu.xib แล้ว xcode จะไปเปิดโปรแกรมที่มีชื่อว่า Interface Builder ขึ้นมา และหน้าของ interface builder ก็จะมีลักษณะประมาณแบบนี้

ทั้งหมดนั้นจะประกอบไปด้วยหน้าต่างที่สำคัญๆ ได้แก่

  • Xib document window
    window นี้จะเป็นส่วนที่บอกว่าใน xib file ของเราประกอบไปด้วยอะไรบ้าง
  • Library window
    สำหรับหน้าต่างนี้จะบอกถึง Class ต่างๆที่เราสามารถใช้งานได้ และถ้าหากเราต้องการสร้าง Button หรือส่วนประกอบต่างๆ ก็ต้องใช้ object จากตรงนี้ในการสร้าง
  • Inspector window
    เป็นส่วนกำหนดค่าต่างๆของ Object นั้นๆ เช่นว่า ความกว้าง ยาว ของ object
  • Connection Panel
    เป็นส่วนสำคัญที่เป็นตัวกำหนดว่า เราจะให้ Object ไหนทำหน้าที่อะไร ส่งหรือรับ message

งั้นเรามาเริ่มออกแบบหน้าตากันเลยดีกว่า วิธีการก็ไม่ยาก เพียงแค่เปิด Library Windows ขึ้นมาก็จะเห็น Object ต่างๆมากมาย ไม่ว่าจะเป็น Button , TextField , Checkbox และอื่นๆมากมาย ก็ลองจับมาวางใส่ให้เป็น ประมาณนี้


ถ้าหากตัวหนังสือตรงปุ่ม ยังเป็นคำว่า Button เราก็เปลี่ยนได้โดยการเลือกที่ Button เปิดหน้าต่าง Inspector Window ขึ้นมา แล้วก็จะเห็นดังภาพ หลังจากนั้นก็แก้ไข ตรง Title ก็เป็นอันเสร็จ

และก็ลองปรับ property ของสิ่งอื่นๆได้เหมือนกันเช่น เราไม่ชอบ Font ของ Label เราก็เปลี่ยนได้ที่หน้า Inspector นี้

Let’s make Class & Object

หลังจากได้ Windows มีัลักษณะหน้าตาประมาณนี้แล้ว ต่อไปก็เริ่มเขียนในส่วนของ Class และตัวโปรแกรมกันเลย

อย่างแรกที่เราจะทำคือ เพิ่ม class เข้าไปใน Project ของเรา โดย class นี้จะเป็นส่วนของตัวโปรแกรมทั้งหมด วิธีการสร้าง class ก็ไม่ได้ยาก และทำได้หลายวิธี แต่ผมใช้วิธีการ click ขวาตรง Folder ด้านซ้ายของ XCode ก็จะเห็นดังรูป เสร็จแล้วเราก็เลือก Add >> New File .. แบบรูปข้างล่างนี้


เมื่อเราเลือกไปที่ Add >> New File .. แล้วก็จะพบหน้าต่างในการสร้างไฟล์ต่างๆมากมาย และใน tutorial นี้เราจะสร้าง Objective-C Class ขึ้นมา เราก็เลือกแบบที่แสดงให้เห็นตามรูปเลย


แล้วเราก็ตั้งชื่อ class ของเราว่า WordCount แบบรูปข้างล่าง

หลังจากนั้นเราจะได้ File มาเพิ่มอีก 2 Files นั่นก็คือ WordCount.m และ WordCount.h



Define method, member


ต่อไปเราก็จะมาเริ่มการเขียน code กัน โดย file แรกทีเราจะเขียนก็คือ WordCount.h

@interface WordCount : NSObject
{
IBOutlet NSTextField *m_textFieldInput;
IBOutlet NSTextField *m_textFieldOutput;
}
- (IBAction) countString:(id)sender;
@end

จาก Code ข้างบน จะเห็นว่าได้ใน WordCount มี แค่ 1 method เท่านั้นนั่นก็คือ

- (IBAction) countString:(id)sender;

จะเห็นว่า method นี้ได้ส่งค่ากลับมาคือ IBAction และรับ parameter เป็น id อธิบายง่ายๆคือว่า method นี้เอาไว้รับ message จาก interface นั่นเอง

เอาง่ายๆว่า ถ้าเราจะเขียนว่า กดปุ่มแล้วให้ไปเรียกใช้ method นี้ เราต้องประกาศใน method ให้เป็น IBAction และรับค่า เข้ามาเป็น id นั่นเอง และอย่าง countString เราก็ต้องการให้กดปุ่ม count แล้วมันมาเรียกใช้ countString

และเรามีตัวแปรอีก 2 ตัวคือ m_textFieldInput และ m_textFieldOutput โดยทั้งสองตัวแปรนี้เป็น NSTextField แต่ที่มีเพิ่มเข้ามาก็คือ IBOutlet เพื่อเป็นการบอกว่า textfield ทั้งสองตัวนี้เป็นตัวแสดง output ไปยัง interface ( จาก window ที่เราออกแบบใน interface builder มาจะเห็นว่า เรามี textField อยู่ 2 อันคือ อันแรกเอาไว้ให้ user พิมพ์ข้อความ ส่วนอีกอันเอาไว้แสดงจำนวนตัวอักษร )

Link Object & Interface

หลังจากเราประกาศ member และ method แล้วต่อไปเราจะเข้าสู่ส่วนสำคัญนั่นก็คือการเชื่อมต่อระหว่าง Interface ที่เราออกแบบ ให้เข้ากับ Class ของเรา

ให้กลับไปยัง Interface Builder แล้วก็ให้เพิ่ม Object เข้า xib ของเรา โดยเปิด หน้าต่าง Library และลากกล่องสีฟ้าๆที่เขียนว่า Object เข้ามาที่ Xib Window ของเราเหมือนดังรูปข้างล่าง


เพื่อที่ว่า เราจะให้ object นี้เป็น instance ของ class ที่เราเขียนขึ้นมานั่นเอง และที่ต้องทำต่อไปก็คือให้ไปที่หน้าต่าง Inspector เพื่อเปลี่ยนกล่องสีฟ้า ให้เป็น object ของ class เรา ดังรูป ( ตรง class ให้เปลี่ยนเป็น WordCount )

ก็เป็นอันเสร็จ เพียงเท่านี้เราก็มี WordCount Object ใน Xib ของเราแล้ว และสิ่งต่อไปที่จะต้องทำก็คือการ เชื่อมระหว่าง Object กับ Interface

โดยสิ่งแรกที่เราจะทำก็คือ เชื่อมระหว่าง m_textFieldInput ของเราเข้ากับ TextField ใน Interface วิธีการก็คือ

  1. Click ขวา ที่ Custom Object ที่เราสร้างขึ้นมา
  2. หลังจากนั้นมันจะเปิดหน้าต่าง ( Connection Panel ) สีดำ
  3. กดไปที่จุดกลมๆข้างหลัง m_textFieldInput
  4. ลากให้เชื่อมต่อกับ TextField ที่เราต้องการ

แบบในรูป

และเราก็ทำต่อในส่วนของ m_textFieldOutput เหมือนๆกัน เพียงเท่านี้ เราก็ได้เชื่อม ระหว่าง textField เข้าด้วยกันแล้ว

แต่ยังเหลือ การเชื่อมต่อ ระหว่าง Action ของเราอีก 1 อย่างนั่นก็คือ เราอยากให้ กดปุ่ม Count แล้วมันไปเรียก countWord นั่นเอง วิธีการก็ไม่ยาก แต่สลับกันนิดหน่อย

  1. กด Click ที่ Button ของเราใน interface
  2. กด Ctrl ค้าง
  3. ลากเส้นสีฟ้า มายัง Custom Object ของเรา
  4. จะมีหน้าต่าง connection panel ขึ้นมาและจะเห็นว่า มี method ที่ชื่อว่า countWord ขึ้นมา แล้วก็กดเลือก

ก็จะเป็นประมาณแบบในรูป

เพียงเท่านี้ก็เสร็จเรียบร้อยแล้ว ณ ตอนนี้เราได้ทำการเชื่อมระหว่าง objcect ของเรา เ้ข้ากับ interface ที่เราสร้างเรียบร้อยแล้ว

Coding

เรายังเหลืองานที่ต้องทำอีกแค่อย่างสุดท้ายนั่นก็คือ implement class ของเรา



@implementation WordCount
-(IBAction) countString:(id) sender
{
NSString *text = [m_textFieldInput stringValue];
if( [text length] != 0)
{
[m_textFieldOutput setIntValue:[text length]];
}
}
@end

จาก code ข้างบน เราได้ นับจำนวน string จาก m_textFieldInput แล้วก็ก็ ใส่ค่าผลลัพธ์ที่ได้ให้กับ m_textFieldOutput

เพียงเท่านี้ก็เป็นอันเสร็จ

Build & Run

และขึ้นตอนสูดท้ายเราก็ Compile แล้วก็ run program ขึ้นมาดู ก็จะเห็นเหมือนในรูป

เพียงแค่นี้เราก็ได้โปรแกรมออกมาแล้ว

Link: http://www.macfeteria.com/2008/07/cocoa-programming-i/

เกริ่นภาพรวมๆของ cocoa

What is Cocoa ?
การเขียนโปรแกรมบน Mac นั้นมี Framework เพื่อให้นักพัฒนาได้ใช้ใช้อยู่ด้วยกัน 2 Framework ใหญ่ๆคือ Carbon และ Cocoa เหตุผลที่ต้องมีถึง 2 Framework นั้นก็เพราะว่า


Carbon นั้นเป็น Framework สำหรับภาษา C/C++

Cocoa เป็น Framework สำหรับภาษา Objective-C

ถ้าหากจะมองเป็นลักษณะภาพโดยรวมว่า Cocoa อยู่ในส่วนไหนของการเขียนโปรแกรมแล้วก็จะได้แบบนี้

โดยปกติแล้วไม่ว่าจะเขียนด้วย cocoa หรือ carbon อย่างใดอย่างหนึ่งก็ตาม class ทั้งสอง Framework จะมีความคล้ายคลึงกันเป็นอย่างมาก อาทิเช่น NSView ( Cocoa ) ก็จะมี class ที่คล้ายๆกันคือ HIView ( Carbon )

แล้วอะไรทำงานเร็วกว่า ?

จากรูปข้างบน ไม่ว่าจะเป็น Carbon หรือ Cocoa เองต่างก็ทำงานในระดับเดียวกัน เพราะสุดท้ายแล้วหลังการ compile เราก็จะได้ Binary ออกมาคล้ายกัน ( แต่ผมคิดว่า ถ้ามองในแง่ของการเขียนโปรแกรมแล้ว ผมว่าเขียน cocoa จะง่ายกว่า carbon เยอะ )

Cocoa Framework
cocoa นั้นประกอบได้ด้วย Framework ย่อยลงไปอีกต่างๆมากมาย โดยแบ่งออกเป็น หลักๆ ได้ 3 ส่วนคือ
  1. Foundation Framework
  2. Application Framework
  3. Other Framework ( CoreData , Sync Services , etc )
ในส่วนของ Foundation Framework นั้นก็ได้แบ่งออกเป็น Class ต่างๆเยอะมากมาย และผมก็ได้ลองพาเขียน objective-c เกี่ยวกับ Foundation Framework มาบ้างแล้ว อาทิเช่น NSString , NSArray เป็นต้น. Class ที่เกี่ยวข้องกับ Foundation Framework นั้นส่วนมากจะเป็น class พิ้นฐาน ไม่ว่าจะเป็น class ที่เกี่ยวกับ string, number ,string , file เป็นต้น

และสำหรับ Appliction Framework เองก็ประกอบด้วย Class มากมายเหมือนกัน ได้แก่ Class ที่เกี่ยวข้องกับ interface ทั้งหลาย เช่นเป็นต้นว่า NSView , NSMenu ,NSToolbar

แต่ไม่ว่าจะเป็น Class อะไรก็ตาม โดยส่วนมากแล้ว Class เหล่านี้จะมี root class เป็น NSObject

Tools

การเขียนโปรแกรมใน Mac นั้นจะมี tools แถมมาให้มากมาย สำหรับ tools ที่จำเป็นกับการเขียน cocoa มีอยู่ด้วยกัน 2 อย่างคือ Xcode กับ Interface Builder

  • XCode
    เป็น IDE ที่เอาไว้เขียนโปรแกรมบน Mac และฟรี โดยจะแถมมากับ Mac อยู่แล้วโดยปกติจะไม่ได้ลงมาให้ เราต้องลงเอง ซึ่งก็ลงได้จาก แผ่น DVD/CD ที่แถมมากับเครื่องนั่นเหละครับ หรือว่าจะไป Download เองที่เวปของ apple ก็ได้ สำหรับคนที่ยังใช้ xcode ไม่เป็น แนะนำให้ไป อ่าน XCode Tutorial หรือว่าจะดูในแบบ XCode Tutorial VDO ก็ได้
  • Interface Builder
    เป็น Tool สำหรับเอาไว้ออกแบบหน้าตาของโปรแกรมว่าจะให้มันมี หน้าตาเป็นแบบไหน และ interface builder นี่เองจะเป็นตัวช่วยให้เราเขียน cocoa ได้ง่ายขึ้นแบบสุดๆ


Link : www.macfeteria.com

Polymorphisms
Polymorphisms สรุปง่ายๆว่าเป็นการอนุญาติให้ derived class ( child class ) สามารถใช้ function ของ parent ได้ สำหรับ polymorphisms นั้นเห็นเด่นชัดมากที่สุดก็คงจะเป็น Overriding / Overloading

Overriding
เป็นการเขียน function ของ Child class ใช้เองโดยไม่ต้องใช้ function ของ Parent Class ถ้าจะยกตัวอย่างง่ายๆ ก็เป็นต้นว่า ถ้าเรามี class ชื่อว่า Car แล้ว Car นั้นมีฟังชั่นขื่อว่า drive สมมติว่าเราจะเขียน class ใหม่ขึ้นมาโดยสืบทอด (inherit) มาจาก Car โดยชื่อว่า Tank มีฟังชั่นชื่อว่า drive เหมือนกัน แต่ว่า class ทั้งสองนั้น Drive ทำงานไม่เหมือนกัน คือพูดง่ายๆว่า รถยนต์ก็ ขับ(drive)ได้ รถถังก็ ขับ(drive) ได้ แต่วิธีการที่จะขับไม่เหมือนกัน
Overloading
เป็นการเขียน Function ชื่อเหมือนกัน ใน class เดียวกัน แต่รับ parameter คนละอย่างกัน เช่นว่า เรามี class ชื่อว่า Rectangle และมี function ในการคำนวนพื้นที่ เราอาจจะต้องการให้มันรับ parameter ได้ทั้ง int และ float ในลักษณะแบบนี้เราก็จะใช้ overloading เข้ามาให้เกิดประโยชน์
อาจจะงง เล็กน้อย สรุปสั้น Overriding ก็คือ child class ที่มีการเขียน function ที่ชื่อเหมือนกับ parent ขึ้นมาเองโดยไม่ต้องสืบทอดจาก parent และ Overloading คือ method ที่สามารถรับ parameter ได้หลายๆรูปแบบ

แต่มาดู code อาจจะเข้าใจง่ายกว่า




// Car.h
#import
@interface Car:Object {
int m_speed;
}
- (void) drive;
- (void) drive:(int)speed;
@end


และในส่วน implement




// Car.m
#import
@implementation Car;
- (void) drive
{
printf("Car drive n");
}
- (void) drive:(int)speed
{
m_speed = speed;
printf ("Car drive at speed %d n",m_speed); }
@end


จากตัวอย่างข้างบนเป็นการ แสดงให้เห็นถึง Overloading คือ จะเห็นว่า Car นั้นมี Function ชื่อเหมือนกัน นั่นคือ drive แต่รับ parameter มาไม่เหมือนกัน โดยที่ drive แรกนั้น ไม่ได้รับ parameter มาเลย ส่วนตัวที่สอง รับ int เข้ามาและ ก็ในส่วนการทำงานของแต่ละฟังชั่นก็ต่างกัน

เวลาเรียกใช้เราอาจจะเขียนได้ว่า



#import "car.h"
int main()
{
Car *honda = [[Car alloc] init];
[honda drive];
[honda drive:80];
return 0;
}

ส่วนผลลัพธ์ที่ออกมาก็จะเป็น

Car drive
Car drive at speed 80

ทีนี้เรามาดู Overriding กันบ้าง ก็อย่างที่บอกไปแล้วว่า เราสารมารถเขียน ให้ child class ทำงานต่างจาก parent โดยที่ ขื่อเหมือนกันได้มาดู กันเลยดีกว่า



// Tank.h
#import "car.h"
@interface Tank:Car {
}
@end

ก็จะเห็นว่าใน class tank นั้นไม่มีอะไรเลย คือ inherit มาจาก car อย่างเดียว
แต่เราสารมารถเขียน implement ของตัวเองโดยอิงจาก parent ได้



#import "tank.h"
@implementation Tank
- (void) drive
{
printf ("Tank Driven");
}
@end

ก็เป็นอันเสร็จ คือเรา เขียน funtion drive ขึ้นมาใหม่ แทนที่ ตัวเก่าที่มีอยู่ใน Car

และก็มาลองเรียกใช้งานกันดู



#import "car.h"
#import "tank.h
int main()
{
Car *honda = [[Car alloc] init];
Tank *tank = [[Tank alloc] init];
[honda drive];
[tank drive];
[tank drive:20];
return 0;
}

ส่วนผลลัพธ์ที่ได้ก็จะได้ว่า
Car drive

Tank drive
Car drive at speed 20

จากผลลัพธ์ก็จะเห็นว่า Tank drive ที่ออกมา โปรแกรมจะไปเรียก function ใน class Tank

ส่วนบรรทัดสุดท้าย ตัวโปรแกรมจะไปเรียกใช้ parent ของ tank นั่นก็คือ Car เพราะเนื่องจากว่า tank นั้น Overriding เพียงแค่ฟังชั่น



- (void) drive;


แต่สำหรับ


- (void) drive:(int)speed;

ไม่ได้ทำการ overriding

มันจึงไปใช้งาน parent ของมันแทน

Dynamic Binding

คือไม่รู้ว่าจะอธิบายง่ายๆได้อย่างไรว่ามันคืออะไร แต่เอาเป็นว่า ขอยกตัวอย่าง Dynamic Binding ให้เห็นภาพได้ว่า สมมติว่า เรามี class ชื่อว่า Dog และ Cat โดนทั้งสอง class นี้เป็น child ของ Animal และมี function ชื่อว่า eat เหมือนกัน ดู code ตัวอย่างภาษา C ต่อไปนี้



void function_eat(Animal *a)
{
a->eat();
}


ถ้าสมมติว่า เราเรียก funciton_eat โดยส่ง pointer ของ Cat และ dog มาให้ในลักษณะแบบนี้


Cat *c = new Cat();
Dog *d = new Dog();
function_eat(c);
function_eat(d);


ะเห็นว่า เราสามารถส่ง ทั้ง Cat และ Dog ไปให้ function_eat ได้ เพราะว่าทั้ง Cat
และ Dog นั้นเป็น Animal ทั้งคู่ ปัญหาก็คือว่าโปรแกรมจะรู้ได้ยังไงว่าควรจะไปเรียก
eat ของ cat หรือว่าไปเรียก eat ของ dog
ตรงนี้ไม่ต้องกังวลเพราะว่าโปรแกรมจะไปตรวจสอบเองว่า Animal ที่ได้รับมาเป็น dog
หรือ cat กระบวนการที่โปรแกรมสามารถจำแนกได้ว่าเป็น class ใดนั้นเหละคือ Dynamic Binding

id Type

ในภาษา objective-c นั้นจะมีตัวแปรชนิดพิเศษที่ชื่อว่า id ตัวแปรชนิดนี้มันจะคล้ายๆลักษณะ pointer ในภาษา C แต่ id มันสามารถ เก็บค่าอะไรก็ได้ !!!

มาดูตัวอย่างอาจจะพอเห็นภาพมากกว่า



#import 
#import

//---------- Human ------------
//------ Human Interface---------
@interface Human:Object
{
}
- (void) printHuman;
@end
//------ Human Implement ------
@implementation Human;
- (void) printHuman
{
printf("Human \n");
}
@end


//---------- Animal ------------
//------ Animal Interface---------
@interface Animal:Object
{
}
- (void) printAnimal;
@end
//------ Animal Implement------
@implementation Animal;
- (void) printAnimal
{
printf("Animal \n");
}
@end


//------ MAIN ---------
int main()
{
id both;
Human *h = [[Human alloc] init];
Animal *a = [[Animal alloc] init];
both = h;
[both printHuman];
both = a;
[both printAnimal];
return 0;
}

คือจาก code ข้างบน ประกาศ class ไว้คือ Human กับ Animal และทั้งสอง class นี้ก็ไม่ได้เกี่ยวกันแต่อย่างได
มาดูที่ main โปรแกรมจะเห็นว่า ประกาศ ตัวแปรมา 3 ตัวก็คือ both , h , a ซึ่งทั้งสามตัวแปรนี้เป็นคนละชนิดกัน จุดที่อยากให้รู้ก็คือว่า เราประกาศ both เป็น id สามารถเก็บอะไรก็ได้ และ

  • เราก็ลองมาให้ both มีค่าเท่ากับ h หลังจากนั้นก็ลองเรียก printHuman
  • เสร็จแล้ว ก็ให้ both มีค่าเท่ากับ a แล้วก็เรียก printAnimal

จะเห็นว่ามันสามารถสลับเปลี่ยนไปเป็น Human หรือ Animal และเรียก function ของทั้งสองได้ ผลลัพธ์ที่ได้ก็จะเป็นแบบนี้

Human
Animal

และการใช้งานลักษณะแบบนี้ก็เป็น dynamic binding นั่นเอง ก็อาจจะเกิดคำถามที่ว่า ก็ในเมื่อมันเก็บได้ทุกอย่าง เราก็ประกาศให้มันเป็น id หมดเลยก็ได้ คำตอบก็คือได้ แต่ไม่ควรทำ ด้วยหลายๆเหตุผล ขอยกตัวอย่างง่ายๆว่า

id a;

กับ

Animal a;

สองอย่างนี้ อะไรเข้าใจง่ายกว่า ว่า a คืออะไร?
ระหว่างบอกว่า a เป็น animal กับ a เป็น id ?
จริงๆมันก็มีอีกหลายๆเหตุผลที่ว่า เราควรใช้ในสิ่งที่จำเป็นมากกว่า ขอยกตัวอย่าง อีกสักอัน

สมมติว่าจาก code ตัวอย่างแรก เรามาแก้ให้เป็นแบบนี้




boht = human;
[both printAnimal];

จะเห็นว่า เราให้ both นั้นเป็น human แต่เรากลับไปเรียกใช้ printAnimal
ซึ่งไม่มีใน Human แน่นอน … แต่เวลา Compile นั้นโปรแกรมจะไม่สามารถตรวจสอบได้ว่า
มันไม่มี printAnimal โปรแกรมจะสามารถ Compile ได้ปกติโดยไม่เกิด
error เพราะว่า dynamic binding นั้นจะเกิดขึ้นตอนโปรแกรมเริ่มทำงาน
ดังนั้นถ้าเราเรียกใช้โปรแกรมดังกล่าว ก็จะเกิด error
ทันที

และจะได้ผลลัพธ์ในลักษณะแบบนี้

Human
error: Animal (Instance)
Animal does not recognize printHuman


ฉนั้นการใช้ก็ควรจะระวังกันสักนิด

สำหรับหัวข้อนี้จะกล่าวถึงรายละเอียดต่างๆเกี่ยวกับ Inheritance (การสืบทอด) ว่ามันคืออะไรและมีความสำคัญยังไง ตั้งแต่พื้นๆก่อนเลยละกัน ก่อนอื่นมาทำความเข้าใจ ของความหมาย ของคำว่า
  • Root class
    ความหมายของ root คือ class ที่ไม่มี parent หรือหมายความง่ายๆว่ามันไม่ได้ไปสืบทอดใคร


  • Parent class
    ส่วน parent นั้นก็คือ class ที่เป็นต้นแบบของ class อื่นๆ และตัว parent เองก็อาจจะสืบทอดคนอื่น(child) มาอีกทีก็ได้


  • Child class
    เป็นการเรียก class ที่สืบทอดมาจากคนอื่น

เพื่อความเข้าใจง่ายๆ ยกตัวอย่าง เรื่องของสัตว์มาประกอบ ก็แล้วกันน่ะสัตว์ทั้งหมดในโลก ขอเรียกว่า เป็น Animal ทั้งหมดเลยแล้วกัน แล้วสัตว์ต่างๆ ก็อาจจะแบ่งออกได้เป็น Mammal ( สัตว์เลี้ยงลูกด้วยนม ) และ Fish ( ปลา ) และ ถ้าในบรรดาเหล่า Mammal ก็มี Dog ซึ่งเป็นสัตว์ชนิดหนึ่งเหมือนกัน
เพื่อความเข้าใจง่ายๆ ดูภาพประกอบ

สำหรับหัวข้อนี้จะกล่าวถึงรายละเอียดต่างๆเกี่ยวกับ Inheritance (การสืบทอด) ว่ามันคืออะไรและมีความสำคัญยังไง ตั้งแต่พื้นๆก่อนเลยละกัน ก่อนอื่นมาทำความเข้าใจ ของความหมาย ของคำว่า

  • Root class
    ความหมายของ root คือ class ที่ไม่มี parent หรือหมายความง่ายๆว่ามันไม่ได้ไปสืบทอดใคร


  • Parent class
    ส่วน parent นั้นก็คือ class ที่เป็นต้นแบบของ class อื่นๆ และตัว parent เองก็อาจจะสืบทอดคนอื่น(child) มาอีกทีก็ได้


  • Child class
    เป็นการเรียก class ที่สืบทอดมาจากคนอื่น

เพื่อความเข้าใจง่ายๆ ยกตัวอย่าง เรื่องของสัตว์มาประกอบ ก็แล้วกันน่ะสัตว์ทั้งหมดในโลก ขอเรียกว่า เป็น Animal ทั้งหมดเลยแล้วกัน แล้วสัตว์ต่างๆ ก็อาจจะแบ่งออกได้เป็น Mammal ( สัตว์เลี้ยงลูกด้วยนม ) และ Fish ( ปลา ) และ ถ้าในบรรดาเหล่า Mammal ก็มี Dog ซึ่งเป็นสัตว์ชนิดหนึ่งเหมือนกัน
เพื่อความเข้าใจง่ายๆ ดูภาพประกอบ


อธิบายตามภาพ

  • Animal เป็น Root Class

  • คลาสที่ต่อออกมาจาก animal ก็คือ mammal ( สัตว์เลี้ยงลูกด้วยนม ) ดังนั้น parent class ของ mammal ก็คือ Animal

  • Fish เป็น class ที่สืบทอดมากจา animal พูดง่ายๆว่าเป็น child ของ animal และก็แน่นอนว่า Fish มี parent class คือ animal เช่นเดียวกัน

  • และสุดท้าย mammal มี child class ที่ชื่อว่า dog และในทางกลับกัน dog ก็จะมี parent class เป็น Mammal

ถ้าหากเราให้คุณสมบัติของ class ต่างๆ เช่นว่า



  • animal เป็นสิ่งมีชีวิตที่ต้องกินอาหาร

  • mammal เลี้ยงลูกด้วยนม

  • fish หายใจในน้ำได้

นั่นก็แปลได้ว่า dog นั้นเป็นสิ่งมีชีวิตที่ต้องกินอาหาร ( สืบทอดจาก animal ) และเป็นสัตว์เลี้ยงลูกด้วยนม ( สืบทอดจาก mammal ) แต่ไม่อาจจะหายใจในน้ำได้เพราะไม่ได้สืบทอดมาจาก Fish


เราลองมาเขียน class จากแผนภาพในแบบง่ายๆกัน

อธิบายตามภาพ

  • Animal เป็น Root Class

  • คลาสที่ต่อออกมาจาก animal ก็คือ mammal ( สัตว์เลี้ยงลูกด้วยนม ) ดังนั้น parent class ของ mammal ก็คือ Animal

  • Fish เป็น class ที่สืบทอดมากจา animal พูดง่ายๆว่าเป็น child ของ animal และก็แน่นอนว่า Fish มี parent class คือ animal เช่นเดียวกัน

  • และสุดท้าย mammal มี child class ที่ชื่อว่า dog และในทางกลับกัน dog ก็จะมี parent class เป็น Mammal

ถ้าหากเราให้คุณสมบัติของ class ต่างๆ เช่นว่า


  • animal เป็นสิ่งมีชีวิตที่ต้องกินอาหาร

  • mammal เลี้ยงลูกด้วยนม

  • fish หายใจในน้ำได้

นั่นก็แปลได้ว่า dog นั้นเป็นสิ่งมีชีวิตที่ต้องกินอาหาร ( สืบทอดจาก animal ) และเป็นสัตว์เลี้ยงลูกด้วยนม ( สืบทอดจาก mammal ) แต่ไม่อาจจะหายใจในน้ำได้เพราะไม่ได้สืบทอดมาจาก Fish

เราลองมาเขียน class จากแผนภาพในแบบง่ายๆกัน






// animal class
@interface Animal
{
string name;
}
- (void) eat;


จาก code ข้างบน ประกาศ class ชื่อว่า animal โดยมี ตัวแปรเป็น string
เอาไว้เก็บชื่อของสัตว์ตัวนี้ และสัตว์ต่างๆก็ต้องการ การกินอาหาร







// Mammal.h
@interface Mammal :Animal
{
int blood_temperature;
}
- (void) feedMilk;


แล้วก็ประกาศ class ชื่อว่า mammal ขึ้นมา โดยสืบทอดมาจาก animal
และก็เพิ่ม method ชื่อว่า feedMilk เข้าไป จากตรงนี้ Mammal
ก็จะสามารถเรียกใช้ method ของ animal ได้ด้วย นั่นก็คือ eat นั่นเอง





// dog.h
@interface Dog :Mammal
{
}
- (void) bite;
- (void) run;


สุดท้ายที่เราประกาศก็คือ dog โดยเพิ่ม method เข้ามาอีกสองอันนั่นก็คือ bite กับ run

สรุปได้ว่า ตอนนี้ dog นั้นสามารถ eat , feedMilk , bite , run ทำได้ทั้ง 4 อย่างเลย
จะเห็นได้ว่า inheritance นั้นมีประโยชน์มาก เพราะว่าเราสามารถ สร้าง class ใหม่ขึ้นมาได้ จาก class ที่มีอยู่แล้ว ทำให้เราลดเวลาการเขียนโปรแกรมลงได้ได้เยอะมาก และเป็นส่วนสำคัญสำหรับ การเขียนโปรแกรมในแบบ OOP ( Object Oriented Programming )


และส่วนตัวของ mammal เองก็มี method ของตัวเองที่ชื่อ feedMilk ด้วย
เลยประกาศ method ชื่อว่า eat ขึ้นมา