ตัวอักษรวิ่ง

ยินดีต้อนรับผู้ที่สนใจเว็บ Blogger ของนายกฤษดา ภูมิเพ็ง สื่อการเรียนการสอนออนไลน์โปรแกรมเชิงวัตถุเบื้องต้น

บทเรียนบทที่ 4

บทที่ 4
Classes และ Objects

              ดังที่ได้อธิบายไว้ในบทแรกนั้น การเขียนโปรแกรมแบบ OOP มีลักษณะเช่นเดียวกับการเขียนโปรแกรมแบบโครงสร้างโดยใช้หลักการที่คล้ายกัน แต่ OOP นั้นจะมีประสิทธิภาพที่สูงกว่า เพราะเป็นการนำเอาคุณลักษณะ (Attribute) และวิธีการ (Method) เช่น ข้อมูล ตัวแปร หรือฟังก์ชั่นของวัตถุนั้นมารวมไว้ในกลุ่มเดียวกันที่เรียกว่า คลาส (Class)
              ในบทนี้จะกล่าวถึงความสัมพันธ์ระหว่างคลาสกับวัตถุ รูปแบบการประกาศคลาสกับวัตถุและส่วนต่างๆ ที่จำเป็นต้องมีในการสร้างคลาสและวัตถุ เช่น Method Constructor และ Destructor เป็นต้น รวมถึงแสดงตัวอย่างโปรแกรมการสร้างคลาสและวัตถุเพื่อนำไปใช้งาน  

ความสัมพันธ์ของคลาสและวัตถุ

การนำเอาแนวคิดของ OOP ที่ศึกษากันไปแล้วมาเขียนโปรแกรมด้วยภาษา C++ โดยจะสมมติคลาสขึ้นมา 1 คลาส โดยให้เป็นคลาสของดินสอ ใช้ชื่อคลาสว่า Cpencil จะได้โค้ดโปรแกรม ดังนี้
              
            จากโปรแกรมในข้างต้นจะเห็นได้ว่า  การประกาศคลาส Cpencil จะมีลักษณะคล้ายกับการประกาศสร้างโดยใช้ Struct ซึ่งภายในคลาสจะประกอบด้วยคุณลักษณะ  (Attribute) และ วิธีการ (Method) ซึ่งต่างจาก Struct ที่จะเป็นการเก็บตัวแปรเพียงอย่างเดียว โดยในที่นี้ตัวแปร Length จะเป็นคุณลักษณะที่ใช้สำหรับเก็บค่าความยาวดินสอ และฟังก์ชั่น write () เป็นวิธีการใช้งานของดินสอนั่นเอง

 

เพราะฉะนั้น เมื่อต้องการสร้างดินสอ 1 แท่งเอาไว้ใช้งานจะต้องเขียนโค้ดโปรแกรม ดังต่อไปนี้

           
การประกาศค่าให้บรรทัดข้างต้น  เรียกว่า “การประกาศออบเจ็กต์” (Object) ซึ่งเป็นการกำหนดให้ Pencil 1 เป็นตัวแปรคลาส C Pencil โดยมี Length ใช้สำหรับเก็บค่าความยาวของ Pencil 1 และมีฟังก์ชั่น write () เป็นวิธีการใช้งานของ Pencil 1 นั่นเอง ถ้ามีดินสอหลาย ๆ แท่งก็สามารถประกาศออบเจ็คต์หลายๆ ตัวได้ เช่น Pencil1, Pencil2, Pencil3 ดังโค้ดโปรแกรมต่อไปนี้

            ออบเจ็กต์ Pencil1 และ Pencil2 ต่างก็จะมีตัวแปร Length และมีฟังก์ชั่น write () เป็นของตัวเองที่เห็นได้ชัด ก็คือ ออบเจ็กต์แต่ละตัวจะเป็นอิสระซึ่งกันและกัน นั่นคือ Pencil Length จะไม่มีทางไปยุ่งวุ่นวายกับ Pencil2 Length ได้เลย เช่นเดียวกับดินสอสองแท่ง ดินสอ Pencil1 อาจจะให้ฟังก์ชัน write () เขียนวงกลม ในขณะที่ดินสอ Pencil2 ใช้ฟังก์ชัน write () วาดรูปสี่เหลี่ยมก็ได้ซึ่งลองพิจารณาจากรูปเพื่อความเข้าใจเกี่ยวกับออบเจ็คต์ และการใช้งานที่แตกต่างกัน
            จะเห็นได้ว่ามีออบเจ็กต์ของคลาสดินสอ 2 ตัวด้วยกัน โดยออบเจ็กต์ตัวหนึ่งเป็นดินสอที่สั้น (ค่าของตัวแปร Length น้อย)และมี write () เป็นการใช้งานดินสอ ซึ่งจะแตกต่างจากออบเจ็กต์อีกตัวหนึ่งที่เป็นดินสอยาว (ค่าตัวแปร Length มาก) และมี write () เป็นการใช้งานดินสอ จะเห็นความเป็นอิสระของออบเจ็กต์อย่างชัดเจน ในการเขียนโปรแกรมจริงๆ นั้น จะได้พบลักษณะของการใช้งานออบเจ็กต์ที่มาจากคลาสเดียวกันแต่ใช้งานต่างกัน ซึ่งจะได้ศึกษาเพิ่มมากขึ้นต่อไปในบทนี้
            คราวนี้ ก็สามารถสรุปได้แล้วว่า
            คลาส (Class) ก็คือ การรวมคุณลักษณะ และการใช้งานของวัตถุอย่างน้อยหนึ่งอย่างมาไว้ในกลุ่มเดียวกัน
            ออบเจ็กต์ (Object) วัตถุที่เป็นตัวแปรคลาส เป็นรูปแบบของคลาสที่มีตัวตนที่สามารถนำไปใช้งานได้

การประกาศคลาส

คลาสเปรียบเสมือนแม่พิมพ์ วัตถุเป็นผลิตผลที่เกิดจากแม่พิมพ์ ดังนั้น การที่จะสร้างวัตถุได้จึงจำเป็นต้องอาศัยแม่พิมพ์หรือคลาสนี้ สำหรับการประกาศคลาสเริ่มต้นด้วยคำหลัก Class ตามด้วยชื่อของ class กำหนดขอบเขตด้วย {} และจบด้วยเครื่องหมาย เซมิโคลอน ( ; )

รูปแบบคำสั่ง


            ตัวอย่างที่จะแสดงต่อไปนี้ คือ การประกาศคลาสวัตถุซึ่งใช้แทนจำนวนตรรกยะ (คือ จำนวนที่อยู่ในรูปเศษส่วน)

ตัวอย่างที่ 4-1 แสดงการประกาศคลาสชื่อ Rational

ฟังก์ชัน assign() convert() invert() และ print() ถูกเรียกว่าฟังก์ชันสมาชิก (Member Functions) เพราะว่าฟังก์ชันเหล่านี้เป็นสมาชิกของคลาสในลักษณะที่คล้ายกัน ตัวแปร num และ den ถูกเรียกว่า ข้อมูลสมาชิก (Member Data) ฟังก์ชันสมาชิกอาจถูกเรียกว่า วิธีการ (Method) ก็ได้
            ในกรณีนี้ฟังก์ชันสมาชิกทั้งหมดได้รับการระบุเป็น public และข้อมูลสมาชิกทั้งหมดได้รับการระบุเป็น private ความแตกต่างระหว่าง public และ private คือ สมาชิกที่เป็น public สามารถเข้าถึงได้จากภายนอก class ในขณะที่สมาชิกแบบ private สามารถเข้าถึงได้เฉพาะภายใน class การป้องกันการเข้าถึงจากภายนอกคลาส เรียกว่า การซ่อน (Encapsulate)
 
ตัวอย่างที่ 4-2 ตัวอย่างการนำคลาสมาทำให้เกิดผลและใช้งานได้(Rational.cpp)



การประกาศวัตถุ

            จากตัวอย่างที่ 4-2 จะเห็นได้ว่า x ได้รับการประกาศเป็นวัตถุของคลาส Rational เนื่องจากเหตุนี้จึงทำให้ x มีสมาชิกข้อมูลภายใน คือ num และ den และมีความสามารถที่จะเรียกใช้ฟังก์ชันสมาชิกจำนวน 4 ตัว ได้แก่ ฟังก์ชัน assign () convert () invert () และ print () สังเกตคือฟังก์ชันสมาชิก เช่น ฟังก์ชัน x.invert () โดยแท้จริงแล้ว ฟังก์ชันสมาชิกสามารถทำการเรียกโดยวิธีนี้เท่านั้น ซึ่งอาจกล่าวได้ว่าเจ้าของการเรียกใช้ คือ วัตถุ x

รูปแบบคำสั่ง


            จากตัวอย่างที่ 4-2 วัตถุ x ได้รับการประกาศเหมือนกับตัวแปรธรรมดาตัวหนึ่งที่เป็นชนิด Rational สามารถพิจารณาได้ว่าข้อมูลชนิดนี้ คือ ข้อมูลที่ผู้ใช้กำหนดขึ้นนอกเหนือจากข้อมูลชนิดอื่นที่ C++ มีอยู่แล้ว อาทิเช่น int float เป็นต้น
            ข้อสังเกต  การใช้ Rational: เป็นตัวเติมข้างหน้าชื่อของฟังก์ชัน เป็นสิ่งจำเป็นสำหรับการนิยามฟังก์ชันสมาชิกที่ให้ไว้ภายนอกเขตของการประกาศ (นอก {}) ตัวดำเนินการกำหนดขอบเขตเขียนด้วยเครื่องหมาย:: ถูกใช้เพื่อผูกการนิยามฟังก์ชันไว้กับคลาส Rational ถ้าปราศจากตัวระบุนี้ คอมไพเลอร์จะไม่รู้ว่าฟังก์ชันนี้ได้รับการกำหนดให้เป็นฟังก์ชันสมาชิกของคลาส Rational
            เมื่อวัตถุ Rational เช่น x ได้รับการประกาศในตัวอย่างที่ 4-2 นั้น กล่าวได้ว่าคลาสได้รับการนำมาใช้และเรียกวัตถุนั้นว่าเป็นกรณีที่เกิดขึ้นของคลาส (Instance) และอาจมีตัวแปรได้หลายตัว ๆ ตัวที่เป็นข้อมูลชนิดเดียวกัน นั่นคือ อาจมีกรณีที่เกิดขึ้นของคลาสหลายๆ ตัว เช่น Rational x, y, z;

ชนิดของวัตถุ (Object Type)
            ในภาษา C++ เมื่อสร้างวัตถุต้องระบุชนิดให้ ซึ่งจะขอยกตัวอย่างเช่น
double convert();
int num,den;
Rational x
      คำว่า double int และ Rational x ก็เป็น Type ให้กับวัตถุที่ตามหลัง โดย Rational เป็น Type ที่เราสร้างขึ้น

Type: boolean char short int long float double 

เมธทอด (Methods)
            เมื่อผู้เขียนโปรแกรมสร้างคลาสเสร็จแล้ว แม้จะยังไม่มีเมธทอด (หรือเรียกอีกอย่างว่า Member Function) และตัวแปร (หรือเรียกอีกอย่างว่า Data Member) ผู้เขียนโปรแกรมสามารถสร้างวัตถุได้ แต่วัตถุที่สร้างขึ้นไม่สามารถเรียกใช้งานได้
            เมธทอด คือ กลุ่มของคำสั่งที่จะทำให้วัตถุบรรลุงานที่ได้รับมอบหมาย และด้วยเหตุนี้ทุกๆ สิ่งจะเกิดขึ้นภายในคลาส ผู้ใช้จึงจำเป็นต้องทราบวิธีสร้างคลาสก่อนสร้าง
เมธทอด
            หากผู้ศึกษาคุ้นเคยกับการเขียนโปรแกรมแบบโครงสร้างมาก่อน Method ตามแนวคิดของ OOP ก็คล้ายกับการเขียนโปรแกรมย่อย (Function) นั่นเอง

รูปแบบคำสั่ง


<return type> คือ กำหนดชนิดของค่าที่จะได้จากเมธทอด ถ้าเมธทอดไม่ได้คืนค่าใดๆ ให้กับผู้เรียก ระบบจะต้อง <return type> เป็น void ในกรณีค่าที่ส่งกลับต้องระบุ <return type> ของเมธทอด ทุกๆ กรณีที่คำนวณได้จากเมธทอดดังกล่าว ซึ่งต้องให้ค่าเป็นเช่นเดียวกับที่ระบุ เช่น ระบุ <return type> เป็น  int ค่าที่คำนวณจะต้องเป็น int มิเช่นนั้นจะเกิดข้อผิดพลาด
            <method name> คือ ชื่อของเมธทอดที่จะใช้ ซึ่งจะต้องเป็นไปตามกฎของการตั้งชื่อ (l<arg List, …>l) คือ ชนิด (ของตัวแปรหรือวัตถุ) และตัวแปรที่ยอมให้เมธทอดผ่านค่าตัวกล่าวไปยังวัตถุ หรือเมธทอดที่เรียกในกรณีที่มี arg List มากกว่า 1 ตัว จะใช้เครื่องหมายคอมม่า (,) คั่นระหว่าง arg

ตัวอย่างเมธทอด

                void print();                                                                                             การประกาศ                                 
                ….
                Void Rational::print()                                                                            รายละเอียด
                {                                                                                                             การทำงาน
                              cout << num >> ‘/’ << den;
                }

การคืนค่า

            ค่าที่ส่งผ่านเมธทอดจะมีค่าที่เป็นตัวเลขใดๆ หรือที่เรียกว่า Pass – by – Value หมายถึงค่าของพารามิเตอร์เหล่านี้จะส่งไปที่พารามิเตอร์ตัวต่อตามลำดับของการประกาศ ให้พิจารณาโค้ดต่อไปนี้
            x.assign (22,7);
            …
            assign (int numerator int denominator)//
            จะเห็นได้ว่า ค่า 22 ส่งไปยังตัวแปร  numerator และส่งค่า 7 ให้กับตัวแปร denominator ตามลำดับ เมื่อมีการส่งผ่านโดยค่าตัวพารามิเตอร์อาจอยู่ในรูปของค่าคงที่ หรือนิพจน์ทั่วๆ ไปก็ได้ ส่วนการส่งอีกแบบ เรียกว่า Pass – by –Reference เป็นค่าอ้างอิงของวัตถุนั้นๆ ซึ่งจะอธิบายต่อไป
            ดังที่กล่าวไปแล้ว เมธทอดจะมีการคืนค่าหรือไม่ก็ได้ ถ้าเมธทอดคืนค่า ค่าที่คืนต้องสอดคล้องกับ Return Type และถ้าเมธทอดไม่คืนค่า หน้าเมธทอดจะต้องระบุคำขยายเป็น void

 

คอนสตรักเตอร์ (Constructor)
คลาส Rational ในตัวอย่างที่ 4-2 ใช้ฟังก์ชัน assign() เพื่อนกำหนดค่าเริ่มต้นให้กับวัตถุ การกำหนดค่าเริ่มต้นให้กับวัตถุนี้ทำได้ง่าย โดยใช้ฟังก์ชันคอนสตรักเตอร์
            Constructor เป็นสิ่งที่ใหม่สำหรับคนที่คุ้นเคยกับการเขียนโปรแกรมเชิงโครงสร้าง (Structural Programming) กล่าวคือ Constructors ไม่มีในภาษาโปรแกรมเชิงโครงสร้าง เช่น C หรือ BASIC เป็นต้น
            Constructors คือ Method ที่มีชื่อเหมือนกับคลาสแต่ไม่มีการส่งค่ากลับ ดังนั้น หาก Method ใดก็ตามมีการส่งค่ากลับก็แสดงว่า Method ดังกล่าวไม่ใช่ Constructor
            คอนสตรักเตอร์ (Constructor) คือ ฟังก์ชันสมาชิกที่ถูกเรียกโดยอัตโนมัติเมื่อวัตถุได้รับการประกาศขึ้น ฟังก์ชันคอนสตรักเตอร์ต้องมีชื่อตรงกับคลาส และได้รับการประกาศแบบไม่มีการส่งค่าคืนกลับ (Return)

ตัวอย่างที่ 4-3 ฟังก์ชันคอนสตรักเตอร์สำหรับคลาส Rational



            ฟังก์ชันคอนสตรักเตอร์มีผลการทำงานเหมือนกับฟังก์ชัน assign() ในตัวอย่างที่4-2
ซึ่งกำหนดค่าเริ่มต้นให้กับวัตถุด้วยการกำหนดค่าให้กับข้อมูลสมาชิก เมื่อการประกาศ x ได้รับการประมวลผล คอนสตรักเตอร์จะทำการเรียกโดยอัตโนมัติ และข้อมูลจำนวนเต็ม
–1 และ 3 จะทำการส่งผ่านค่าไปยังพารามิเตอร์ n และ d ต่อจากนั้นฟังก์ชันจึงกำหนดค่าเหล่านี้ให้กับข้อมูลสมาชิก num และ den ดังเช่นการประกาศต่อไปนี้
                                    Rational x(-1,3),y(22,7);
                                    จึงมีค่าเท่ากับประโยคทั้งสาม ดังต่อไปนี้
                                                Rational x;
                                                x.assign(-1,3);
                                                y.assign(22,7);
            ในทางตรงกันข้าม หากต้องการสร้าง Constructor อีกตัว และต้องการกำหนดค่าเริ่มต้นของพารามิเตอร์นั้น สามารถทำได้ดังนี้
            วิธีการที่สามารถสร้าง Constructor ได้หลายๆ ตัวโดยที่ยอมให้มีการใช้ชื่อเหมือนกัน (แต่พารามิเตอร์ที่ส่งผ่านให้กับ Contractor นั้นแตกต่างกัน) เรียกวิธีการนี้ว่า Overloading ส่วนของ Method เรียกว่า (Overloading a Method)

รายการกำหนดค่าเริ่มต้นคอนสตรักเตอร์

            คอนสตรักเตอร์ส่วนใหญ่ไม่ทำอะไรมากไปกว่าการกำหนดค่าเริ่มต้นให้กับข้อมูลสมาชิกของวัตถุ ผลที่ตามมา คือ C++ ได้จัดหาอุปกรณ์รูปแบบพิเศษสำหรับคอนสตรัคเตอร์ซึ่งทำให้เขียนโปรแกรมได้ง่าย อุปกรณ์ที่ว่านี้ คือ รายการกำหนดค่าเริ่มต้น
            นี่คือคอนสตรักเตอร์ที่สองในตัวอย่างที่ 4-3 ซึ่งนำมาเขียนใหม่โดยใช้รายการกำหนดค่าเริ่มต้น
            Rational (int n, int d): num (n), den (d){}
            ประโยคกำหนดค่านั้น กำหนด n ให้กับ num และ d ให้กับ den ที่ถูกลบทิ้งไป การปฏิบัติการของตัวนิพารามิเตอร์ได้รับการดำเนินการโดยรายการกำหนดค่าเริ่มต้นที่แสดงไว้ในส่วนที่เขียนด้วยตัวหนา สังเกตว่า รายการกำหนดค่าเริ่มต้นนั้นมีเครื่องหมาย : และอยู่ก่อนหน้าตัวฟังก์ชัน {} ซึ่งในที่นี้มีแต่ความว่างเปล่า
            นี่คือคลาส Rational ที่มีคอนสตรักเตอร์ 3 ตัว นำมาเขียนใหม่ด้วยการใช้รายการกำหนดค่าเริ่มต้น

ตัวอย่างที่ 4-4 การใช้รายการกำหนดค่าเริ่มต้นในคลาส Rational



            การเขียนคอนสตรักเตอร์ทั้ง 3 ชุดแบบแยกจากกันนั้นไม่จำเป็น เพราะสามารถเขียนรวมกันเป็นคอนสตรักเตอร์เดียวด้วยการใช้ค่าพารามิเตอร์
ตัวอย่างที่ 4-5 การใช้ค่าพารามิเตอร์ในคอนสตรัคเตอร์คลาส Rational


           

ในที่นี้ x จะแทนค่า 0/1 y จะแทนค่า 4/1 และ z จะแทนค่า 22/7
ดีสตรักเตอร์ (Distracter)
            เมื่อมีการสร้างวัตถุ คอนสตรักเตอร์จะได้รับการเรียกโดยอัตโนมัติ ในลักษณะเดียวกันเมื่อวัตถุได้มาถึงจุดสิ้นสุดขอบเขต ฟังก์ชันสมาชิกเฉพาะกิจอื่นๆ จะถูกเรียกโดยอัตโนมัติเพื่อจัดการทำลายตัวเอง ฟังก์ชันนี้ เรียกว่า ดีสตรักเตอร์ (Destructor)
            คลาสแต่ละคลาสจะมีดีสตรักเตอร์ที่แน่นอนหนึ่งตัว ถ้าไม่ได้ถูกนิยามได้อย่างชัดเจนในการนิยามคลาสแล้ว ก็จะเหมือนกับคอนสตรักเตอร์โดยปริยาย คือ เป็นค่าที่กำหนดให้ต้องเป็น
ตัวอย่างที่ 4-6 การรวมดีสตรักเตอร์ไว้ในคลาส Rational


 



            ผลลัพธ์นี้จะแสดงให้เห็นเมื่อคอนสตรักเตอร์และดีสตรักเตอร์ถูกเรียกใช้ ดีสตรักเตอร์ คลาสได้รับการเรียกสำหรับวัตถุเมื่อถึงจุดสิ้นสุดของขอบเขต สังเกตได้จากการใช้ {} เพื่อแบ่งขอบเขต

การสร้างโปรแกรม

            ต่อไปจะเป็นการนำเอาความรู้ที่ได้เรียนรู้นำมาประยุกต์เขียนโปรแกรมโดยใช้ Visual C++ ซึ่งต้องการสร้างคลาส Time วัตถุแต่ละตัวของคลาสนี้จะแสดงเวลาของวัน โดยจัดเก็บชั่วโมง นาที และวินาที เป็นจำนวนเต็ม โดยรวมคอนสตรักเตอร์ เมธทอด ซึ่งมีฟังก์ชันการทำงานดังนี้ Advance (int h int m int s) เพื่อเพิ่มค่าเวลาปัจจุบันของวัตถุที่ปรากฏอยู่ในขณะนั้น ฟังก์ชัน Reset (int h int m int s) เพื่อล้างค่าเวลาปัจจุบันของวัตถุที่ปรากฏอยู่ และเมธทอด print ()

 ขั้นตอนที่ 1 สร้างโปรเจ็กต์ Time Zone
            ให้สร้างโปรเจ็กต์ใหม่ด้วย Win32 console Application โดยไปที่ File>New คลิกแท็บ Project เลือก Win32 Console Application และตั้งชื่อ Project
ขั้นตอนที่ 2 สร้างคลาส Time
            ไปที่ File>New คลิกแท็บ Files เลือก C++ Source File พร้อมกับตั้งชื่อ File
ขั้นตอนที่ 3 พิมพ์โค้ดโปรแกรมลงใน Time.cpp ซึ่งมีดังนี้



ในที่นี้ใช้ฟังก์ชัน normalize() ซึ่งตั้งค่ามาตรฐานให้กับวัตถุ Time เพื่อให้สมาชิกข้อมูลทั้งสามอยู่ในช่วงข้อมูลที่ถูกต้อง ดังนี้ 0<=sec <60,0 <=min<60 และ 0<=hr<24
ขั้นตอนที่ 4 ทำการ save โดยไปที่ เมนู File>Save All หรือกด Ctrl+sและคอมไฟล์ โดยคลิกที่เมนูบาร์ของ Build หรือกดแป้นลัด (Shortcut Key) Ctrl+F7 ยังไม่ต้องสร้าง Link File เนื่องจากยังไม่มีการเรียกใช้งาน class นี้
ขั้นตอนที่ 5 ทดสอบการทำงานด้วยการเพิ่มโค้ดลงไปยัง Time.cpp ตัวอย่างเช่นโด้ดดังนี้

 

Main()
{
                Time x;
                x.advance(20,15,25);
                x.print();
                return 1;
}

 

 

 

           

 

 

ตามด้วยคอมไพล์ และสร้าง Link File ด้วยการกด F7 แล้วดูผล Run ด้วยการกดปุ่ม Ctrl+F5 ซึ่งจะปรากฏหน้าจอ ดังนี้

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

ไม่มีความคิดเห็น:

แสดงความคิดเห็น