Talk: Mac Pro

จริงว่าจะไม่เขียนเรื่องส่วนตัวเท่าไหร่ แต่ก็คิดว่าถ้ามันเกี่ยวกับ mac ก็น่าจะเขียนบ้าง คือเนื่องจากวันก่อนผมเข้าไปดูที่เวปของ Apple ( ปกติไม่ค่อยเข้า ) ก็เห็น Spec ของ Mac Pro จริงๆก็ออกได้ตั้งแต่ช่วงมกราคมแล้วละ เห็นแล้วก็ร้องเพราะว่า ความแรงมันต่างกันกับเครื่องปัจจุบันเหลือเกิน คือเครื่องปัจจุบันของผม ก็ Mac Pro น่ะ Xeon Quard core , Ram 4 Gb.

ก็น่าจะเรียกได้ว่าเทพพอสมควร แต่ว่าพอเห็นเครื่อง Mac Pro ใหม่แล้วก็ต้องบอว่าของผม มันเด็ก เพราะว่าตัวใหม่มัน Xeon 8-Core ขอกรี๊ดสักที ให้ตายเหอะ ราคาก็เท่ากันอีกต่างหาก คือเพิ่งได้เครื่องมาตอน พฤษศจิกายน มามกราคม มันออกใหม่แรงกว่าเดิม ในราคาเท่าเดิม นี่มันระยะเวลาแค่ 3 เดือนเองน่ะ แต่ก็เอาเถอะไม่คิดมาก เพราะว่าไม่ใช่เงินเรา บริษัทออกให้ แต่ก็แอบเซ็งเล็กน้อย แต่ก็อย่างว่างานส่วนมากของผมคือ เขียนโปรแกรม บน Mac เนี่ยสิ งานเลยไม่ได้ยุ่งกับ Graphic มากเท่าไหร่ แต่ว่า ก็ต้องใช้เครืองแรงๆ เพราะว่าโปรแกรมที่เขียนมันเกี่ยวกับ 3D ใช้แต่ Xcode แต่ก็ยังดีใจอย่างว่า อีกราวๆ 2 อาทิตย์ บริษัทจะซื้อ Mac book pro มาด้วย ไว้ให้มันได้มาก่อนจะได้เอามายลโฉม เจ้า MBP

Pure Virtual

คือจาก เมื่อวันที่ผ่านมา เนื่องจากว่า งานที่ทำอยู่มีส่วนต้องให้ port โปรแกรมจาก Win มาสู่ mac และบังเอิญว่า ผม compile แล้วมันผ่าน แต่ว่าตอน Runtime มันดัน Error สิ่งที่มันบอกมาก็คือว่า pure virtual method called terminated called with out an active exception ปัญหาที่เกิดขึ้น ก็ยัง งงๆๆว่าเป็นเพราะอะไร แต่พอหลังจากให้เพื่อนมาดูแล้วก็นั่งถกกัน ว่ามันเกิด เฉพาะกับ mac หรือเปล่าเพราะว่าใน win ไม่เห็นมันจะเกิด ก็เลยทำการเขียน code ที่ทำงานแบบเดียวกัน ก็ัดังตัวอย่างข้างล่าง

ก็ถ้า ดูตาม code ก็จะเห็นว่า มี Base กับ Derived เนื่องจากว่า Base Class มันเป็น Pure Virtual (Abtract Class) เราต้อง implement ส่วนของ code การทำงานใน derived class เสมอไม่อาจจะเขียน implement ใน Base Class ได้ และปัญหาจากโปรแกรมข้างบนเกิดขึ้นเพราะในขณะที่ base class ได้เรียก destructor ของตัวเองนั้น มันกลับไปเรียกใช้งานฟังชั่นใน derived class ด้วย ซึ่งนั่นก็ทำให้มันเกิด error เพราะว่า derived class ได้ถูกทำลายไปก่อนแล้ว ทำให้ไม่สามารถเรียกได้

ลองดูตรง

จาก destructor นี้จะเห็นว่า มีการเรียกฟังก์ชั่น foo และแน่นอนว่า foo ไปเรียก

อีกที สืบเนื่องจากว่ามันเป็น pure virtual แปลว่าตัว Base Class เองไม่อาจจะเขียน implement code ได้มันจึงต้องไปเรียก banana ในตัว Derived Class ที่มีการเขียน implement code และ Derived นั้นได้ทำลายจาก destructor ไปเรียบร้อยแล้ว มันเลยไม่เจอ banana ทำให้เกิด error นั่นเอง

ลองศึกษา เพิ่มเติมเกี่ยวกับ Virtual Function ได้ที่ http://en.wikipedia.org/wiki/Virtual_function

Objective-C Programming II : More about Class – Inheritance

สำหรับหัวข้อนี้จะกล่าวถึงรายละเอียดต่างๆเกี่ยวกับ 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 จากแผนภาพในแบบง่ายๆกัน

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

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

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

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

Objective-C Programming Part II.

หลังจากที่เขียน Objective-C ไปแล้วอันแรก ผมคิดว่าถ้าจะเริ่มตั้งแต่ ชนิดของตัวแปร Loop , if-else ก็คิดว่าคงจะใช้เวลาไปหน่อย กว่าจะเขียนเสร็จ ( คือถ้าจะเอาให้ละเอียดเนี่ยสงสัยว่าเขียน หนังสือเลยอาจจะดีกว่า ) เอาเป็นว่า จากนี้ผมขอคิดว่า คนที่อ่านบทความของผม นั้น มีความรู้เกี่ยวกับ C/C++ มาบ้าง ซึ่งสิ่งที่คุณต้องรู้มาก่อนก็คือ

  • Data type
    ก็จำพวกว่า สามารถประกาศ int , char , array ได้ประมาณนี้ก็พอ
  • Expression
    เป็นต้นว่า เข้าใจการใช้งาน if – else , neatest if-else อะไรทำนองนี้
  • Function
    ใช้งานฟังชั่นในเบื้องต้นเป็น รวมทั้งความเข้าใจในการส่ง Parameter และการส่งค่ากลับของ function
  • Pointer
    เข้าใจการทำงานของ pointer และการใช้งานเป็นในระดับหนึ่ง
  • Basic Memory Management
    รู้และเข้าใจการจอง memory และการใช้งาน เป็นต้นว่า malloc , free , delete

คือเพราะว่า โดยภาษา Objective-C นั้น มีการใช้งาน Syntax คล้ายๆกับ ภาษา C และ java ค่อนข้างมาก สำหรับคนที่ไม่เคยเขียน โปรแกรมมาก่อน แนะนำว่า ควรไปศึกษา C/C++ มาก่อน ( ผมว่าจะเขียน เหมือนกันแต่เอาให้ obj-c เสร็จก่อนละกัน )

การเขียน Class

การเขียน class ในภาษา objc นั้นจะแบ่งออกเป็น สามส่วนหลักๆคือ

  1. interface
  2. implement
  3. program

ในภาษา objc นั้น มีรูปแบบการประกาศแบบนี้ครับ

การประกาศ class นั้นจะเริ่มด้วย @interface แล้วก็ตามด้วยชื่อของ classname และสำหรับ :parentClassname นั้นก็เป็นส่วนที่บอกว่า class นี้สืบทอด (inheritance) มาจาก class ไหน ในส่วนของ data member นั้นจะประกาศภายในเครื่องหมาย { และ } ส่วน function จะทำการประกาศ ข้างนอก { } และปิดท้ายด้วย @end

เอาละมาดูตัวอย่าง class แรกของเราเลยละกัน

เราทำการสร้าง class ขึ้นมาใหม่ ชื่อว่า Book ซึ่งประกอบไปด้วย ข้อมูลสองอย่างคือ book_id และ price โดย class นี้สืบทอดมาจาก NSObject และประกอบด้วย 5 method ( function ) นั่นคือ

  • – (void) printDetail ;
    สำหรับ method นี้ ได้สั่งค่ากลับเป็นแบบ void ( พูดอีกนัยได้ว่าไม่ต้องส่งค่ากลับ )
  • – (void) setPrice: (float) p;
    ในส่วนของ setPrice นั้นมีการส่งค่ากลับเป็นแบบ void เหมือนกัน แต่ว่าสิ่งที่ต่างจาก printDetail คือ มีการรับ parameter เข้าไปด้วย โดยรับเข้าไปเป็น int และให้ parameter นี้ชื่อว่า p
  • – (void) setID: (int) id;
    ทำงานเหมือนกับ setPrice แต่เป็นการใส่ค่าให้กับ book_id
  • – (void) setPriceAndID: (float) p : (int) id;
    method นี้จะทำการรับ ค่า parameter เข้ามาสองค่า คือ float กับ int การรับค่า parameter เข้ามาหลายๆค่านั้น จะทำการ แบ่งด้วยเครื่องหมาย : (โคล่อน )
  • – (float) getPrice;
    ฟังชั่นนี้จะทำการส่งค่า price กลับไปเป็นแบบ float

เพียงเท่านี้ก็เป็นการประกาศ Class แบบง่ายๆเสร็จแล้ว

อาจจะงงว่าทำไมต้อง inherit มาจาก NSObject ด้วย ก็ขออธิบายเพิ่มเติมง่ายๆว่า มันคือ Root ของ class ต่างๆในภาษา objective-c สำหรับคำว่า NS นั้น ย่อมาจาก NextStep (เป็นชื่อของบริษัทเก่าที่ Steve Job เคยตั้ง) NSObject นั้นจะมี function ที่สำคัญอันได้แก่ การจอง memory ( alloc ) ให้กับ object นั้นๆ และการ เลิกการจอง ( dealloc) พูดง่ายว่า การประกาศ class ใหม่นั้นต้องสืบทอดมาจาก class นี้

เมื่อทำการประกาศ class ไปแล้ว เรายังเหลือส่วนที่ต้องเขียน นั่นก็คือ ส่วนของ implementation งั้นมาดูกันเลย

ก็เป็นว่าเสร็จในส่วนของการ implementation แล้ว เหลือส่วนสุดท้ายนั่นก็คือ program

Sending Message

สำหรับ ภาษา  objective-c นั้นจะทำการเรียก function หรือว่า method ว่าเป็นการส่ง message ไปให้มัน ซึ่งรูปแบบก็คือ

[receiver message];

ซึ่งถ้าเทียบกับภาษา C/C++ ก็จะได้ประมาณว่า

receiver->message();

เหมือนเราต้องการจะให้ receiver นั้นทำอะไร เราก็ต้องบอกให้มันทำให้เรานั่นเอง

ขออธิบายในส่วนของ main program กันก่อนละกัน

เราเริ่มประกาศตัวแปร scibook ให้เป็น pointer ของ Book และทำการส่ง message ที่ชื่อว่า alloc ไปให้ Book เพื่อทำการจอง memory แล้วหลังจากการจองแล้ว ก็ยังไม่สามารถใช้ได้เลย ต้องทำการ initialize มันซะก่อน ด้วยการส่ง message บอกให้ init อีกที

ปล. initialize คือการให้ค่าเริ่มต้นสำหรับตัวแปรต่างๆ เพราะว่าในการจอง memory  นั้น พื้นที่ที่โดนจองอาจจะมีค่าต่างๆที่หลงเหลือจากโปรแกรม อื่นๆ เราก็ต้องปัดกวาด พื้นที่ตรงนั้นให้มันพร้อม เสียก่อน

สำหรับ บรรทัดต่อมา เป็นการรวมสองบรรทัดเข้าด้วยกันเลย ก็จะได้ว่า

การทำงานเหมือน กับ scibook เลยแค่ ลดให้มันเหลือ 1 บรรทัด อาจจะมองได้ดังรูปต่อไปนี้

receiver

เมื่อเรามี object แล้วก็สามารถเรียกใช้ function โดยการส่ง message ไปให้ object เช่น

จากตัวอย่างเป็นการส่ง message ที่ชื่อว่า setID และส่ง parameter ที่มีค่าเป็น 1 ไปให้ตัวแปรที่ชื่อ mathbook ด้วย
และส่วนสุดท้าย

เป็นการส่ง message ที่ชื่อ release เพื่อคืนหน่วยความจำให้กับระบบ เราต้องทำทุกครั้งเมื่อจะจบโปรแกรม เพราะว่าไม่งั้นมันจะไม่รู้ว่าโปรแกรมของเราได้ยกเลิกการใช้งานในพื้นที่ตรงนั้นไปแล้ว

ถ้าลอง compile และ run ก็จะได้ผลลัพธ์แบบนี้ครับ

ก็ลองๆ โหลด source file ไป compile ดูได้ครับ

Objective-C Programming Part I Source File

Objective-C Programming Part I.

การเขียนโปรแกรมบน mac ก็อย่างที่บอกไปแล้วว่า มี 2 ภาษาหลักๆคือ c/c++ กับ obj-c ผมคิดว่าถ้าจะเขียน c/c++ programming ก็คิดว่าหนังสือภาษาไทยก็เยอะแล้ว เลยเขียนเกี่ยวกับ objective-c จะดีกว่า เริ่มกันเลยดีกว่า เริ่มจากการสร้าง file นามสกุล .m ขึ้นมาก่อนเช่นเป็นต้นว่าชื่อ hello.m และส่วนข้างใน hello.m ก็มี code แบบนี้

เมื่อเสร็จแล้ว ก็ save แล้วก็เปิด terminal ขึ้นมาแล้วก็สั่ง compile ด้วยคำสั่ง gcc hello.m -o hello -l objc แล้วหลังจากนั้น ก็ ทำการเรียกโปรแกรม ขึ้นมาด้วยคำสั่ง ./hello จะเห็นข้อความว่า

ดังตัวอย่างรูปข้างล่าง

terminal

ก็เป็นอันเรียบร้อยจาก code ตัวอย่าง ถ้าใครเขียนภาษา C/C++ มาก่อนจะเห็นว่ามันแทบจะไม่ต่างกันเลยจะต่างกันก็แค่ #import ถ้าเป็น ภาษา c/c++ จะใช้ #include ส่วนนามสกุลของ source นั้นจะเป็น .m ก็อธิบายตาม code ข้างบนก็คือว่า

  • #import <stdio.h> เป็นการนำ file stdio.h เข้ามาเพื่อที่ว่าเราจะได้สามารถเรียกคำสั่งที่อยู่ภายใน file stdio.h ได้ เป็นต้นว่า printf
  • int main(int argc, const char -argv[] สำหรับบรรทัดนี้ เป็น ส่วนเริ่มต้นของโปรแกรม และการทำงานต่างๆจะอยู่ระหว่าง { กับ }
  • printf(“Hello world!”); เรียกฟังชั่น printf เพื่อที่จะแสดงผลคำว่า Hello world ที่ console
  • return 0; การส่งค่า 0 กลับไปให้ยัง os

และในส่วนของการ compile น้ันเราได้ใช้ gcc เป็นเครื่องมือในการ compile โดยเราได้เรียก  gcc hello.m -o hello -l objc ก็อธิบายได้ว่า

  • -o หมายถึง output ที่ได้จากการ compile ในที่นี้ก็คือ hello
  • -l objc หมายถึงว่า เป็นการ linking กับ Objective-C Runtime library ที่ชื่อว่า objc

จากตัวอย่างข้างต้น จะเห็นว่าเราสามารถเขียนโปรแกรม และ compile ได้โดยไม่ต้องอาศัย เครื่องมือใดๆ นอกจาก gcc และ text editor สักตัว แต่การเขียนโปรแกรมโดยที่ไม่มี Tool หรือ IDE เป็นตัวช่วยเลยนั้น เป็นเรื่องที่ค่อนข้างลำบาก พอสมควร แต่อย่างไรก็ตาม เรามีเครื่องมือที่ช่วยในการเขียนโปรแกรมให้ง่ายขึ้น ที่มาพร้อมกับ mac และยังฟรีอีกด้วย นั่นคือ xcode

สำหรับตอนนี้ก็จบเพียงเท่านี้เหละครับ