C Programming : เขียนโปรแกรมภาษา C แบบพื้นฐาน ตอนที่ 6 – การเขียนโปรแกรมเชิงวัตถุ
บทความตอนที่ 6 เป็นต้นไป จะเป็นการต่อยอดจากภาษา C ขึ้นไปอีกระดับ คือภาษา C++ ซึ่งภาษา C++ ก็คือ การความสามารถให้กับตัวภาษา C ความสามารถนั้นคือการรองรับสิ่งที่เรียกว่า OOP (Object Oriented Programming) ผมจะยังไม่อธิบายว่าอะไรคือ OOP มันมีอะไรบ้างในตอนนี้ ผมจะค่อยๆอธิบายหลักการเป็นเรื่องๆไป แล้วจะนำไปสู่การอธิบายเรื่อง OOP ในภายหลัง ซึ่งใน C++ จะมีการใช้ : (Colon) และ . (Dot) เพิ่มเข้ามา เราก็ค่อยๆจำว่า มันใช้งานอย่างไรบ้าง
รู้จักคลาส (Class)
สำหรับมือใหม่ที่ไม่รู้จัก class ต้องทำเข้าใจเรื่องนี้ให้ดี สรุปสั้นๆคือ มันก็คือการเอาตัวแปรกับฟังชันก์ที่มีความสัมพันธ์กันจับมาอยู่เป็นกลุ่ม
ยกตัวอย่าง Class ของนักเรียน ให้ชื่อว่า Student ภายในจะประกอบไปด้วย ชื่อนักเรียน คะแนนนักเรียน ฟังชันก์ก็มีการทำงาน เช่น เปลี่ยนชื่อนักเรียน การเรียกดูเกรด จะเห็นว่าเป็นเรื่องของนักเรียนทั้งหมด
ดังนั้น class ของครู ก็มีเรื่องเกี่ยวกับคุณครู และ class ของมอนเตอร์ในเกม ก็จะมีข้อมูลเกี่ยวกับ HP , Level อะไรต่างๆ ทำให้เรื่อง class เอาไปประยุกต์ได้แทบทุกเรื่อง
ดู code ตัวอย่าง เดี๋ยวอธิบายด้านล่าง
#include<stdio.h> #include<string.h> class Student{ public:char firstname[100] ="John"; public:char lastname[100] ="Lennon"; public:int score = 50; void setFirstName(char newName[]){ strcpy(firstname,newName); } void setLastName(char newName[]){ strcpy(lastname,newName); } }; main(){ Student s; printf("\nfirstname = %s",s.firstname); printf("\nlastname = %s",s.lastname); printf("\nScore = %d",s.score); }
สังเกตว่าชื่อ class จะตั้งตัวแรกนำหน้าเป็นตัวใหญ่ เช่น Student อันนี้เป็นธรรมเนียมปฏิบัติ ส่วนชื่อตัวแปรจะเป็นตัวเล็ก จากนั้นลอง save เป็น ไฟล์ .c แล้ว RUN (หรือกด F11 ในโปรแกรม Dev C++)
จะเห็นว่า มันขึ้น Error
นั่นก็เพราะว่าไฟล์ .c ซึ่งมันใช้ C compiler มันไม่รองรับการใช้งาน class นั่นเอง ให้เรา save เป็นไฟล์ .cpp แทน ดังนั้นต่อแต่นี้ให้ save เป็น .cpp นะ
แล้วลองรันอีกครั้ง
จาก code จะเห็นว่ามีการปริ้นชื่อ แล้วก็คะแนนออกมา
บรรทัดที่ 4, 5, 6 คือการประกาศตัวแปรใน class โดยสังเกตจะมีคำว่า public อันนี้เป็นอีกความสามารถนึงใน C++ เรียกว่า Access Modifier เดี๋ยวอธิบายในหัวข้อถัดๆไป
บรรทัดที่ 9 – 15 เป็นการประกาศฟังชันก์ใน class คือ กำหนดค่าต่างๆ
บรรทัดที่ 10 -14 จะเห็นว่ามีการใช้คำสั่ง strcpy อันนี้คือ String Copy มันก็คือการกำหนดค่าให้กับตัวแปร char[]
บรรทัดที่ 19 คือการประกาศตัวแปร Student
บรรทัดที่ 20, 21, 22 คือการปริ้นค่าจากตัวแปรใน class สังเกตว่าเอาตัวแปรของ class มาใส่ . แล้วก็เข้าถึงตัวแปรได้เลย
นอกจากนั้นเราสามารถเขียนนิยามฟังชันก์ไว้นอก class ได้ด้วย โดยต้องกำหนดชื่อ , return type และ parameter
public:void setFirstName(char newName[]); public:void setLastName(char newName[]);
จากนั้นก็ไปเขียนเพิ่มเติมด้านนอก class แต่ก็ต้องระบุชื่อ class
void Student::setFirstName(char newName[]){ strcpy(firstname,newName); } void Student::setLastName(char newName[]){ strcpy(lastname,newName); }
ตัวอย่าง code ทั้งหมด
#include<stdio.h> #include<string.h> class Student{ public:char firstname[100] ="John"; public:char lastname[100] ="Lennon"; public:int score = 50; public:void setFirstName(char newName[]); public:void setLastName(char newName[]); }; void Student::setFirstName(char newName[]){ strcpy(firstname,newName); } void Student::setLastName(char newName[]){ strcpy(lastname,newName); } main(){ Student s; printf("\nfirstname = %s",s.firstname); printf("\nlastname = %s",s.lastname); printf("\nScore = %d",s.score); }
รู้จัก Method
Method คือ ฟังชันก์ใน class ดังนั้น setFirstName() และ setLastName() ใน Stduent จะเรียกว่า method
ทีนี้ต่อไปถ้ามันเป็นฟังชันก์ที่อยู่ใน class ผมจะเรียกมันว่า method นะ
ลองใช้งาน method ที่ชื่อว่า setFirstName() setLastName() โดยเราต้องส่งค่าเป็น parameter 1 ตัว คือ char[] เพื่อกำหนดค่าชื่อ
s.setFirstName("Benznest"); s.setLastName("Jan"); printf("\nfirstname = %s",s.firstname); printf("\nlastname = %s",s.lastname);
ลองรันจะเห็นว่า firstname , lastname ถูกเปลี่ยนแปลงแล้ว
สรุป
s.lastname = “Jan” คือการกำหนดค่าแบบใช้ตัวแปรโดยตรง
s.setLastName(“Jan”) คือการกำหนดค่าผ่าน method ของ class
แล้วเราควรใช้แบบไหนล่ะ? ที่นิยมคือแบบที่สองเพราะมันยืดหยุ่นกว่า
ต่อไปจะลองทำ method แบบที่ดึงค่า หรือ get ค่าออกมาเพื่อแสดงบ้าง
ในที่นี้ผมจะเขียน method ชื่อว่า getGrade ซึ่งจะไปดูคะแนน score ของนักเรียนแล้วก็ return grade A B C D F ออกมา
class Student{ ... public:char getGrade(){ if(score < 50){ return 'F'; } else if(score < 60){ return 'D'; } else if(score < 70){ return 'C'; } else if(score < 80){ return 'B'; } else{ return 'A'; } } }; main(){ Student student2 = Student(); printf("\nStudent2 Grade = %c",student2.getGrade()); }
เรียกใช้ method getGrade() ได้เลย
จะเห็นว่า ได้ grade = D เพราะว่าเราไปกำหนดค่าเริ่มต้นเป็น 50
ซึ่ง method ที่มีคำนำหน้า set get จะใช้เยอะมากๆ เพราะเราจำเป็นต้องกำหนดค่า หรือดึงค่าตัวแปรมาใช้งานอยู่บ่อยๆ
รู้จัก Overloading method
overload คือ ฟังชันก์หรือ method ที่สามารถมีชื่อเหมือนกันได้หลายตัว แต่ต้องมี parameter ต่างกัน ซึ่งในภาษา C เดิมทำไม่ได้
ทำให้เราสามารถเขียนโปรแกรมได้ยืดหยุ่นขึ้น เช่น setName() ก็สามารถตั้งค่าชื่อจากหลายวิธีการ
void setName(char newFirstname[],char newLastname[]){ // } void setName(char newFullname[]){ // }
รู้จัก Constructor
constructor คือ method ที่จะถูกเรียกหลังจากที่ object ถูกสร้างทันที โดยทั่วไปเอาไว้สำหรับให้กำหนดค่าเริ่มต้นให้กับตัวแปรใน object โดย constructor จะมีชื่อเดียวดับ class และไม่มี return type
เช่น Student นี้ มี 2 constructor
ตัวแรกไม่รับ parameter คือสร้างแบบเปล่าๆ
ตัวที่สองจะรับพารามิเตอร์ 2 ตัว คือ firstname,lastname ก็คือหลังจากสร้างแล้วจะนำ parameter ไปทำการกำหนดค่า
จริงๆจะมีกี่ตัวก็ได้ parameter เป็นอะไรก็ได้
class Student{ public: char firstname[100]; public: char lastname[100]; public:int score = 50; Student(){ setFirstName("Panuwat"); setLastName("Jan"); } Student(char newFirstname[],char newLastname[]){ setFirstName(newFirstname); setLastName(newLastname); } }
วิธีใช้งานก็ง่ายๆแบบนี้
Student student1 = Student(); Student student2 = Student("Justin","Beber");
รู้จัก Destructor
destructor คือคำสั่งที่จะถูกเรียกเมื่อ object ถูกทำลายนั่นคือตอนหมดขอบเขตของมัน หรือสิ้นสุดโปรแกรม
แต่ก็สามารถเรียกให้ทำลายด้วยคำสั่ง delete ได้เช่นกัน
#include<stdio.h> class Student{ public: char firstname[100]; public: char lastname[100]; public:int score = 50; Student(){ } ~Student(){ printf("\nDestructor Student called."); } }; main(){ Student s1 = Student(); delete &s1; }
รู้จัก Object และ Instance
สองคำนี้เป็นคำที่มาคู่กับ class มันคือตัวแปรที่ถูกสร้างขึ้นแล้ว โดยมี class เป็นนิยาม ความหมายตามความเข้าใจของผมคือมันเหมือนกันแล้วแต่จะเรียก
สรุป class เป็นแค่การนิยามว่าเอาตัวแปร เอาฟังชันก์ต่างๆที่มีความสัมพันธ์ มาอยู่รวมกัน แต่ยังไม่ได้ถูกสร้าง
ดังนั้นในกรณีของตัวอย่าง
Student student1 = Student();
Student เป็นคลาส
student1 , student2 เป็น object
รู้จัก Access Modifiers
Access modifier คือการจำกัดการเข้าถึงของ object โดยจากตอนต้นเราจะเห็นคำว่า public
มันคือการจำกัดการเข้าถึงข้อมูลภายใน class โดยตัวแปรจะมี 3 modifier
public คือ อนุญาตให้ภายนอกเข้าถึงได้ เข้าถึงจากในคลาสตัวเองได้ และสามารถสืบทอดได้
private คือ อนุญาตให้เข้าถึงจากในคลาสตัวเองเท่านั้น สืบทอดไม่ได้
protected คือ อนุญาตให้เข้าถึงจากในคลาสตัวเองเท่านั้น และสามารถส่งต่อให้ class ที่มาสืบทอดได้
เดี๋ยวอธิบายเรื่องสืบทอดในหัวข้อถัดไป หากไม่ใส่ มันจะมองเป็น private อัตโนมัติ
ค่อยๆดูไปทีละตัวนะ ลองดูตัวอย่างของ private ก่อน เราจะกำหนดทุกตัวแปรให้เป็น private
#include<stdio.h> #include<string.h> class Student{ private: char firstname[100]; private: char lastname[100]; private:int score = 50; private:Student(){ } void setFirstName(char newName[]){ strcpy(firstname,newName); } }; main(){ Student student1 = Student(); printf("\nStudent1 Score = %s",student1.score); }
เมื่อลอง RUN จะเห็นว่ามันมัน Error เพราะ constructor Student() มันใช้งานได้เฉพาะในคลาสตัวเอง จะเรียกจากใน main ไม่ได้ ดังนั้น constructor ส่วนใหญ่จะใช้เป็น public
ทีนี้ลองแก้ให้ Student() เป็น public
... public:Student(){ } ...
แล้ว RUN ก็จะ error อีกเพราะ ตัวแปร score เรากำหนดเป็น private
พอไปเรียก student1.score จาก main() มันเป็นการเข้าถึงโดยตรงจึงทำไม่ได้
วิธีแก้ก็สามารถเปลี่ยน score เป็น public เหมือนก่อนหน้านี้ก็ได้
แต่อีกวิธีนึงที่สามารถทำได้คือให้ score เป็น private เหมือนเดิม แต่ใช้การ get ค่าผ่าน method แล้วให้ method นั้นเป็น public แทน ซึ่งวิธีที่สองจะเหมาะสมกว่าเพราะเป็นการใช้ความสามารถของ Access Modfier กับ Class ให้เป็นประโยชน์ และในหลายๆกรณี object ของเราก็ต้องการรับ parameter หรือไม่ต้องการให้เรียกใช้งานตัวแปรโดยตรง
class Student{ private:int score = 50; public:Student(){ } public:int getScore(){ return score; } }; main(){ Student student1 = Student(); printf("\nStudent1 Score = %d",student1.getScore()); }
ตอนนี้ พอจะเห็นภาพเรื่อง Public Private กันแล้วนะครับ ทีนี้มาดูอีกตัวคือ Protected ซึ่งมันจะมาพร้อมกับเนื้อหาอีกเรื่องคือ การสืบทอด (inheritance)
รู้จักการสืบทอด (Inheritance)
การสืบทอด มันคือการส่งต่อตัวแปรและ method ของ class ไปยังอีก class นึง จะเรียกว่า class แม่ ส่งต่อให้ class ลูกอะไรทำนองนั้นก็ได้ มาดูตัวอย่างกัน
เรามี class ชื่อว่า Person ซึ่งภายในมีข้อมูลพื้นฐานเช่น ชื่อ อายุ
แล้วก็มี class ชื่อ Student มีข้อมูลคะแนนนักเรียน อีกอันคือ Teacher ภายในมีข้อมูล subjectId สำหรับบอกว่าสอนวิชาอะไร
ซึ่งทั้ง Student และ Teacher ก็ต่างต้องมีข้อมูล ชื่อ อายุ เช่นกัน ดังนั้นเราไม่จำเป็นต้องประกาศตัวแปร ชื่อ อายุ ใน Student /Teacher เราแค่ประกาศใน Person แล้วให้ทั้งสองมาสืบทอดไปนั่นเอง
วิธีการใช้งาน คือ ด้านหลังชื่อ class ลูก ก็เขียนต่อท้ายว่าต้องการสืบทอดจาก class ไหน
class Student: public Person{ ... }
ทีนี้การสืบทอดก็สามารถสืบทอดได้หลายแบบ คือ Public / Private / Protected
หลังจากสืบทอดแล้ว ลูกๆจะได้รับผลเป็นไปตามนี้
class A { public:int x; protected:int y; private:int z; }; class B : public A { // x is public // y is protected // z is not accessible from B }; class C : protected A { // x is protected // y is protected // z is not accessible from C }; class D : private A // 'private' is default for classes { // x is private // y is private // z is not accessible from D };
จากตัวอย่างของเรา เราก็เลยสามารถเรียกว่า Person คือ class แม่ แล้ว Student,Teacher เป็นคลาสลูก
โดยให้ class ลูกสืบทอดแบบ public เพราะว่า ถ้าเราสืบทอดแบบ private ตัวแปรและ method ที่สามารถสืบทอดมาจะกลายเป็น private แล้วจะทำให้เราเรียก method จาก main มาใช้งานไม่ได้ แล้วถ้าเราสืบทอดแบบ protected ตัวแปรและ method ที่สามารถสืบทอดมาจะกลายเป็น protected ซึ่งก็ไม่ต่างกับ private เลย คือเรียกใช้งานจาก main ไม่ได้ เพียงแต่มันจะยังสามารถส่งต่อไปยัง class ลูกของมันต่อได้เท่านั้น ดังนั้นผลคือ สืบทอด public เหมาะสมกับกรณีนี้ และเป็นเคสที่มักจะใช้บ่อยที่สุด
#include<stdio.h> #include<string.h> class Person{ protected: char firstname[100]; protected: char lastname[100]; protected: int age; public:int getAge(){ return age; } public:void setAge(int newAge){ age = newAge; } }; class Student:public Person{ private:int score = 50; public:int getScore(){ return score; } }; class Teacher:public Person{ private:int subjectId = 1; public:int getSubjectId(){ return subjectId; } }; main(){ Student s = Student(); s.setAge(9); printf("Student age = %d",s.getAge()); }
ลองรันจะเห็นว่าเราสามารถเรียกใช้งาน method ที่ชื่อว่า setAge() และ getAge() จาก student ได้ทั้งๆที่เราประกาศไว้ใน class Person แสดงว่า getAge() และ getAge() ถูกส่งต่อมายัง Student แล้วนั่นเอง
การสืบทอดจากหลายคลาส (Multi-Inherit)
การสืบทอดสามารถสืบทอดมาจากหลาย class ได้ด้วย มาดูตัวอย่าง
ผมมี class Person , Employee แล้วให้ Teacher สืบทอดมาจาก 2 class นั้น
#include<stdio.h> #include<string.h> class Person{ protected: char firstname[100]; protected: char lastname[100]; protected: int age=50; public:int getAge(){ return age; } }; class Employee{ protected: double salary = 15000; public:double getSalary(){ return salary; } }; class Teacher:public Person,public Employee{ private:int subjectId = 1; public:int getSubjectId(){ return subjectId; } }; main(){ Teacher t = Teacher(); printf("\n Teacher age = %d",t.getAge()); printf("\n Teacher salary = %.0lf",t.getSalary()); }
ผลก็คือ Teacher สืบทอดทั้งตัวแปร และ method มาจาก class แม่ทั้งสองนั่นเอง
ดังนั้น การออกแบบ class จึงเป็นเรื่องสำคัญเพราะมันหมายถึงโครงสร้างของงานเลยทีเดียว มันจึงมีศาสตร์อีกหลายอย่างที่จะมาอธิบายหลักการนี้ แต่โดยพื้นฐานสรุปๆก็คือ เราต้องมองให้ออกว่าอะไรควรเป็น class บ้าง อะไรคือ class แม่ อันไหนคือ class ลูก แล้วอะไรคือ class หลานๆต่อไป อันไหนสืบทอดอันไหน อันนี้ก็อยู่ที่ประสบการณ์และการฝึกฝน
รู้จัก Polymorphism
Polymorphism คือกลไกที่ตัวแปรของ class แม่ สามารถเป็น class ลูกได้ ทำให้ันสามารถมีได้หลายรูปแบบนั่นเอง ตามชื่อของมัน
ลองดูตัวอย่าง code
#include<stdio.h> #include<string.h> class Person{ public:virtual void hello (){ // } }; class Student:public Person{ public:void hello(){ printf("\n Hello Student"); } }; class Teacher:public Person{ public:void hello(){ printf("\n Hello Teacher"); } }; main(){ Student s = Student(); Teacher t = Teacher(); Person *person; person = &s; person->hello(); person = &t; person->hello(); }
เรามี class ชื่อว่า Person เป็น class แม่ แล้วมี Student , Teacher มาสืบทอดไป แต่ละ class มี method ชื่อว่า hello() ซึ่งจะปริ้นชื่อ class ออกมา โดย method hello() ของ class แม่มีคำว่า virtual
public:virtual void hello (){ // }
ที่ main เราประกาศตัวแปร Student , Teacher และตัวแปร pointer ของ Person
ทีนี้ก็ให้ person ชี้ไปที่ student , teacher แล้วเรียก method hello()
จะพบว่ามันสามารถเรียก hello() ของ class Student และ Teacher ได้ ทั้งๆที่ตัวแปรเป็นประเภท Person
นั่นก็เพราะว่า class แม่ สามารถมีรูปแบบเป็น class ลูกนั่นเอง
รู้จัก Override
override คือการระบุคำสั่ง method ใน class ลูกทับแทน method ที่มีชื่อเดียวกัน และparameter เหมือนกันใน class แม่
ซึ่งในตัวอย่างจากด้านบน เราจะเห็นว่ามีการ override method ชื่อว่า hello() นั่นเอง ซึ่งเรื่องนี้ก็ถูกใช้งานบ่อยมากๆ
class Person{ public:virtual void hello (){ // } }; class Student:public Person{ public:void hello(){ printf("\n Hello Student"); } };
รู้จัก Overloading Operator
Overloading Operator คือการเพิ่มความสามาราถของ operand ให้กับ class
เช่นเอา object มาบวก ลบ คูณหารกัน แล้วได้ object ใหม่เป็นต้น ซึ่งมีการนำมาใช้งานบ่อยพอสมควร
เช่นใน code ตัวอย่างนี้ ผมมี class Student จากนั้นผมจะทำการเพิ่ม Operator + ให้กับ class
ทำให้ผมสามารถนำ object Student มา + กันได้ ส่วนกระบวนการทำงานก็แล้วแต่เราจะทำอะไร ซึ่งในที่นี้ผมจะนำคะแนน score มาบวกกัน
#include<stdio.h> #include<string.h> class Student{ private: char firstname[100]; private: char lastname[100]; private:int score = 50; public:Student(){ } public:Student operator+ (Student s){ Student newStudent = Student(); newStudent.setScore(score + s.getScore()); return newStudent; } public:void setScore(int newScore){ score = newScore; } public:int getScore( ){ return score ; } }; main(){ Student s1 = Student(); s1.setScore(61); Student s2 = Student(); s2.setScore(55); Student sumStudent = s1 + s2; printf("Sum Student Score = %d",sumStudent.getScore()); }
จะเห็นว่าเราสามาราถนำ object ของ Student มา + กันได้
อีกตัวอย่าง คือการใช้ ++ มา Overloading Operator
ซึ่งสามารถใช้ได้ทั้งแบบ prefix , postfix
prefix คือ ++student
postfix คือ student++
ซึ่งโดยปกติถ้าเราใช้กับตัวแปร int มันก็จะบวกค่า 1 แต่คราวนี้เราจะมาใช้กับ object และจะทำอะไรก็ได้
เช่น ++student จะให้เพิ่มคะแนน score +5 ส่วน student++ จะให้ +10
วิธีการก็เหมือนเดิมแต่แค่ prefix ไม่ต้องใส่ parameter ส่วน postfix ให้ส่วน parameter ว่า int เฉยๆ
#include<stdio.h> #include<string.h> class Student{ private: char firstname[100]; private: char lastname[100]; private:int score = 50; public:Student(){ } public:void operator++ (){ score = score +5; } public:void operator++ (int){ score = score +10; } public:void setScore(int newScore){ score = newScore; } public:int getScore( ){ return score ; } }; main(){ Student s1 = Student(); s1.setScore(0); s1++; ++s1; printf("Student Score = %d",s1.getScore()); }
โดยใน C++ รองรับการ Overloading Operator ถึง 42 ตัว
รู้จักการห่อหุ้ม (Encapsulation)
Encapsulation คือ คอนเซ็ปที่กำหนดการเข้าถึงตัวแปรใน class โดยอนุญาตให้เข้าถึงผ่านช่องทางที่กำหนดเท่านั้น ใช่แล้วมันคือการใช้ Access modifier เช่นพวก public, private, protected ร่วมกับ class นั่นเอง และนี่คือเหตุผลว่า ทำไมควรกำหนดตัวแปรเป็น private/protected แล้วกำหนด method สำหรับ set/get เป็น public
ยินดีต้อนรับสู่โลกของ OOP การเขียนโปรแกรมเชิงวัตถุ
หากคุณอ่านมาถึงตรงนี้ และคุณเป็นมือใหม่ที่ไม่รู้จัก OOP มาก่อน ขอยินดีต้อนรับครับ เพราะทั้งหมดในบทความนี้คือ คอนเซ้ปพื้นฐานของ OOP ทั้งหมด ซึ่ง OOP แปลเป็นภาษาไทยคือการเขียนโปรแกรมเชิงวัตถุ ที่บอกว่ามันเป็นวัตถุก็คือ object ที่ถูกสร้างจาก class นั่นเอง และอย่างที่ผมบอกด้านบนว่า class คืออะไรที่สำคัญมาก
โดยกฏของ OOP จะมี 4 อย่าง คือ
1. Abstraction หมายถึง การนิยาม class ก่อนที่จะนำ class ไปสร้างเป็น object
2. Encapsulation ก็พวก public , private นั่นเอง
3. Inheritance คือ การสืบทอดจาก class แม่ไป ลูก
4. Polymorphism ก็ที่ object แม่สามารถเป็น object ลูกได้หลายรูปแบบ
สรุป
บทความนี้พามารู้จักกับหลายๆเรื่องในโลกของ OOP พามารู้จักกับความสามารถที่เพิ่มขึ้นของ C กลายเป็น C++ ที่เพิ่มความยืดหยุ่นให้กับการเขียนโปรแกรมอีกหลายๆอย่างมากๆ หากคิดว่าบทความมีประโยชน์หรืออยากแนะนำตรงจุดไหน คอมเม้นได้เลยครับ