การใช้งาน Class กับโปรแกรมเชิงวัตถุ OOP ในภาษา Dart เบื้องต้น
เขียนเมื่อ 3 ปีก่อน โดย Ninenik Narkdeeconstructors dart การใช้งาน class โปรแกรมเชิงวัตถุ oop ในภาษา dart
คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ constructors dart การใช้งาน class โปรแกรมเชิงวัตถุ oop ในภาษา dart
UPDATE! อัพเดทล่าสุด 21-11-2019
* 21-11-2019 | เพิ่มเติมเนื้อหาของ factory และ constant constructor ตอนท้าย
* 21-11-2019 | เพิ่มเติมเนื้อหาของ factory และ constant constructor ตอนท้าย
ไปที่ Copy
ในเนื้อหาในตอนต่อไปนี้ เราจะมาดูเกี่ยวกับการใช้งาน class เบื้องต้นในภาษา Dart
ตั้งแต่การกำหนด class การใช้งานงานตัวแปรใน class ที่เรีรยกว่า states หรือ property
การใช้งานฟังก์ชั่นการทำงานใน class ที่เรียกว่า method รวมถึงการใช้งานและการกำหนด
constructor ของ class เป็นต้น
สามารถทดสอบการเขียนโปรแกรมผ่านเว็บไซต์ DartPad
การกำหนด Class
เนื่องจากภาษา dart เป็นรูปแบบภาษาโปรแกรมเชิงวัตถุ (OOP) ทุกสิ่งใน dart ล้วนเป็น object และทุกๆ object ล้วนถูกสร้างมาจาก class
โดย class เปรียยสมือนพิมพ์เขียวหนึ่งๆ ที่สามารถนำไปสร้างเป็น object ได้หลายๆ ตัว ยกตัวอย่างเช่น เราต้องการสร้างพิมพ์เขียวหุ่นยนต์
ขึ้นมา (เรากำลังจะสร้าง class) และให้หุ่นยนต์ที่เราจะสร้างนั้น อาจจะมี property ต่างๆ เช่น ชื่อหรือหมายเลข ใช้พลังงานจากอะไร เป็นต้น
รวมไปถึงหุ่นยนต์นี้มีฟังก์ชั่นการทำงานหรือการกระทำอะไรที่สามารถทำได้ เช่น สามารถเดินได้ พูดได้ บินได้ นั่งได้ เต้นได้ เหล่านี้ ก็จะเป็นฟังก์ชั่น
การทำงาน หรือใน class ก็จะเรียกฟังก์ชั่นว่า method
มาเริ่มสร้าง class หุ่นยนต์ตามความเข้าใจเบื้องต้นกัน
void main () { } // การสร้าง class class Robot{ // state หรือ property ของ class หรือก็คือตัวแปร // สำหรับกำหนดคุณลักษณะ ของ class นั้นๆ String codeName; double height; bool walkable; bool talkable; // ฟังก์ชั่นการทำงาน หรือ method ที่จะบอกว่า หุ่นยนต์นั้น // ทำอะไรได้บ้าง void walking(){ // เดินได้ print("Walking..."); } void talking(){ // พูดคุยได้ print("Talking..."); } }
จะเห็นว่าในการสร้าง class เราเพียงกำหนด class keyword ด้านหน้า แล้วตามด้วยชื่อ class แล้วเปิดปิดด้วยเครื่องหมาย { } ภายในก็จะเป็นการกำหนด
ตัวแปรต่างๆ เป็น property และกำหนดฟังก์ชั่น เป็น method โดยทั้งสองส่วนล้วนเป็นเนื้อหาที่เราได้ทำความเข้าใจมาแล้ว ทบทวนได้ที่
ตัวแปร Variable ในภาษา Dart http://niik.in/939
Function ในภาษา Dart http://niik.in/941
ตัวอย่างโค้ดข้างต้น เรากำหนด class ชื่อ Robot ประกอบด้วย property ที่ชื่อ codeName, Height, walkable และ talkable และมี 2 method คือ
walking() และ talking() นี้คือพิมพ์เขียวของ Robot ที่เราสร้างขึ้น ต่อไป เราต้องการนำพิมพ์เขียวนี้ไปสร้างเป็น หุ่นยนต์ 2 ตัว โดยสามารถทำได้ดังนี้
void main () { var humanoidA = Robot(); // สร้าง Robot object print(humanoidA.runtimeType); // Robot var humanoidB = Robot(); // สร้าง Robot object print(humanoidB.runtimeType); // Robot }
เราสร้างตัวแปร humanoidA และ humanoidB เป็นตัวแปรอ้างอิง หรือที่เรียกว่า reference variable ให้มีค่าเท่ากับ instance of Robot object
ซึ่่งรูปแบบที่เราคุ้นเคยคือ
var humanioidA = new Robot();
แต่ในภาษา dart เราไม่ระบุ "new" keyword ก็ได้ จึงได้เป็น
var humanoidA = Robot();
การเรียกใช้ Robot() เป็นการสร้าง Robot object ขึ้นมา ตัวแปร humanoidA จึงมีค่าเท่ากับ instance object ของ Robot ดังนั้น เมื่อเราทดสอบ
แสดงประเภทของตัวแปร โดยใช้คำสั่ง runtimeType เราก็จะได้ว่า humanoidA และ humanoidB ล้วนเป็น Robot หนึ่งๆ นั่นเอง
การใช้งานตัวแปรและฟังก์ชั่นใน class
หลังจากที่เราทำการสร้าง instance object ขึ้นมาและเก็บไว้ในตัวแปร humanoidA และ humannoidB ข้างต้นแล้ว เราก็สามารถเรียกใช้งาน
ตัวแปรและฟังก์ชั่นที่อยู่ใน object นั้นๆ ได้ โดยเราจะเรียกว่า instance variable และ instance method ตามลำดับ
void main () { var humanoidA = Robot(); // การใช้งาน instance variable // การกำหนดค่า หรือเรียกว่า default setter humanoidA.codeName = 'ZA-05'; humanoidA.height = 200; humanoidA.walkable = true; humanoidA.talkable = true; // การอ่านค่า หรือเรียกว่า default getter print(humanoidA.codeName); // output: ZA-05 // การเรียกใช้งาน instance method humanoidA.walking(); humanoidA.talking(); var humanoidB = Robot(); // การใช้งาน instance variable // การกำหนดค่า หรือเรียกว่า default setter humanoidB.codeName = 'ZB-03'; humanoidB.height = 180; humanoidB.walkable = true; humanoidB.talkable = false; // การอ่านค่า หรือเรียกว่า default getter print(humanoidB.codeName); // output: ZB-03 // การเรียกใช้งาน instance method humanoidB.walking(); }
โค้ดตัวอย่างข้างต้น เราทำการเรียกใช้งาน ตัวแปรภายใน object ที่สร้างมาจาก class เราเรียกว่า instance variable โดยทดสอบทำการ
กำหนดค่าให้กับตัวแปรนั้น หรือที่เรียกว่าการกำหนด default setter และทดสอบอ่านค่าโดยแสดงข้อมูลค่าของตัวแปร codeName หรือเรียกว่า
การใช้งาน default getter นอกจากนั้น เรายังทดสอบเรียกใช้งาน instance method หรือฟังก์ชั่นใน class
การใช้งาน Constructors
เราสามารถสร้าง object โดยใช้ constructor เพื่อกำหนดค่าให้กับ property ของ object ผ่านการกำหนด parameters constructor ได้ ก่อนลง
รายละเอียด เรากลับมาดูที่ class Robot ของเราก่อน
class Robot{ String codeName; double height; bool walkable; bool talkable; // หาก class นั้นไม่ได้กำหนด constructor // จะมี default constructor เป็นชื่อเดียวกับ ClassName Robot(); // เรียกว่า default construtor void walking(){ // เดินได้ print("Walking..."); } void talking(){ // พูดคุยได้ print("Talking..."); } }
Default Constructor
จะเห็นว่า หากเรากำหนด class โดยไม่มีการกำหนด constructor ตัว class นั้นๆ จะมี default constructor เป็นชื่อเดียวกับ class อย่างโค้ดตัวอย่างข้างต้น
Robot() เป็น default constructor ที่ไม่มีการทำงานใดๆ ไม่มีการกำหนด parameter ดังนั้น เราจึงไม่จำเป็นต้องกำหนดค่านี้ ก็ได้ แต่สมมติว่า เราต้องการให้
ทำคำสั่งใดๆ ทันทีที่ทำการสร้าง object เราสามารถกำหนด default constructor โดยมีส่วนของ body เพื่อทำคำสั่งที่ต้องการได้ ตัวอย่างเช่น
void main () { var humanoidA = Robot(); // สร้าง Robot object humanoidA.codeName = 'ZA-05'; humanoidA.height = 200; print(humanoidA.codeName); humanoidA.walking(); humanoidA.talking(); var humanoidB = Robot(); // สร้าง Robot object humanoidB.codeName = 'ZB-03'; humanoidB.height = 180; print(humanoidB.codeName); humanoidB.walking(); } class Robot{ String codeName; double height; bool walkable; bool talkable; // default constructor Robot(){ print("Default constructor runtime"); } void walking(){ // เดินได้ print("Walking..."); } void talking(){ // พูดคุยได้ print("Talking..."); } }
ผลลัพธ์ที่ได้เมื่อรันคำสั่ง
Default constructor runtime ZA-05 Walking... Talking... Default constructor runtime ZB-03 Walking...
จะเห็นว่า default constructor จะทำงานทุกครั้ง ทันทีที่มีการสร้าง object หรือมี instance object เกิดขึ้น
Parameter Constructor
หากเราต้องการสร้าง object พร้อมกับกำหนด parameter ให้สามารถที่จะส่งค่าไปใช้งานใน object นั้น สามารถทำได้ดังนี้
สมมติเราส่งค่า codeName กับ height เข้าไป จะได้เป็น
// parameter constructor Robot(String codeName, double height){ this.codeName = codeName; this.height = height; }
หรือเขียนในรูปแบบดังนี้แทนก็ได้
// parameter constructor Robot(this.codeName, this.height){ // คำสั่งอื่นๆ เพิ่มเติม ถ้ามี }
หรือกรณีต้องการกำหนดค่าอย่างเดียว ก็สามารถไม่กำหนดในส่วนของ body ให้กับ constructor ก็ได้ จะได้เป็น
// parameter constructor Robot(this.codeName, this.height);
รูปแบบการใช้งาน parameter constructor ข้างต้น เป็นการกำหนดค่าให้กับตัวแปร ในขั้นตอนการสร้าง object ผ่าน parameter ดังนั้น รูปแบบ
การเรียกใช้งาน ก็จะต้องปรับใหม่ โดยต้องทำการส่งค่า argument ไปด้วย ดังนี้
void main () { var humanoidA = Robot('ZA-05', 200); // สร้าง Robot object // ตัวแปร codeName และ height ถูกกำหนดค่าไปแล้วในขั้นตอนการสร้าง object print(humanoidA.codeName); // output: ZA-05 humanoidA.walking(); humanoidA.talking(); var humanoidB = Robot('ZA-05', 180); // สร้าง Robot object // ตัวแปร codeName และ height ถูกกำหนดค่าไปแล้วในขั้นตอนการสร้าง object print(humanoidB.codeName); // output: ZA-05 humanoidB.walking(); }
ในภาษา Dart เรายังมีวิธีการสร้าง object โดยสามารถเจาะจงความจำเพาะ ของ object นั้น โดยการใช้งาน named constructor โดยจะมีรูปแบบ
การกำหนด named constructor คือ ClassName.identifier โดย identifier คือคำจำเพราะ หรือคำที่ต้องการระบุแยกย่อยให้ชัดเจนในการสร้าง object นั้นๆ
Named Constructor
สมมติเราต้องการสร้าง named constructor สำหรับสร้าง Robot object รุ่นเริ่มต้น ที่มี codeName ชื่อ "Demo-00" และ height เท่ากับ 150 เราสามารถ
กำหนด named constructor ใน Robto class ได้เป็นดังนี้
void main () { var humanoidA = Robot('ZA-05', 200); // สร้าง Robot object var humanoidB = Robot('ZA-05', 180); // สร้าง Robot object // สร้าง Robot object จาก named constructor var humanoidC = Robot.origin(); print(humanoidC.codeName); // output: Demo-00 } class Robot{ String codeName; double height; bool walkable; bool talkable; // parameter constructor Robot(this.codeName, this.height); // named constuctor Robot.origin(){ codeName = "Demo-00"; height = 150; } void walking(){ // เดินได้ print("Walking..."); } void talking(){ // พูดคุยได้ print("Talking..."); } }
จะเห็นว่า origin เป็น identifier ที่เราต้องการกำหนดเจาะจง เป็นค่าอะไรก็ได้ ตามต้องการ สมมติ เราสร้างรุ่นพิเศษ ขึ้นมาใช้ชื่อว่า extra และมีการ
ใช้งาน parameter ร่วมด้วย เป็นดังนี้
// named constuctor with parameter Robot.extra(this.codeName, this.height, this.talkable);
เวลาเรียกใช้งาน ก็จะได้เป็น
// สร้าง Robot object จาก named constructor และใช้งาน parameter var humanoidD = Robot.extra('EX-01', 300, true); if(humanoidD.talkable){ humanoidD.talking(); // output: Talking... }
เราสามารถกำหนด named constructor เท่าไหร่ก็ได้ ตามต้องการ ในขณะที่ parameter constructor จะสามารถกำหนดได้แค่ครั้งเดียวเท่านั้น
เราสามารถกำหนดทั้ง parameter constructor และ named constructor พร้อมกันได้
Redirecting constructor
ในกรณีที่เราต้องการส่งต่อบางค่า ไปใช้งานใน constructor หลัก เราสามารถทำการ redirect ค่านั้นโดยการกำหนดรูปแบบ constructor เป็น
redirecting constructor ดูตัวอย่างโค้ดดานล่างประกอบ
// Redirecting constructors Robot.smart(String codeName):this(codeName, 150);
เรากำหนด named constructor ที่ชื่อ Robot.smart() ได้รับ parameter ที่เป็น codeName ค่าเดียว จากนั้นเรากำหนด : (colon) แล้วเรียกใช้งาน
constructor หลัก หรือก็คือ Robot(this.codeName, this.height) โดยส่งต่อ codeName ใน parameter แรก และฟิกค่า height เท่ากับ 150 ใน
parameter ตัวที่สอง ดังนั้น this(codeName, 150) จึงหมายถึงการเรียกใช้งาน constructor หลักนั่นเอง ดูตัวอย่างโค้ดเต็มประกอบ
void main () { var humanoidA = Robot('ZA-05', 200); // สร้าง Robot object var humanoidB = Robot('ZA-05', 180); // สร้าง Robot object // สร้าง Robot object จาก named constructor var humanoidC = Robot.origin(); print(humanoidC.codeName); // output: Demo-00 // สร้าง Robot object จาก named constructor และใช้งาน parameter var humanoidD = Robot.extra('EX-01', 300, true); if(humanoidD.talkable){ humanoidD.talking(); // output: Talking... } // สร้าง Robot object จาก redirecting constructor var humanoidE = Robot.smart('SM-01'); print(humanoidE.codeName); // output: SM-01 print(humanoidE.height); // output: 150 } class Robot{ String codeName; double height; bool walkable; bool talkable; // parameter constructor Robot(this.codeName, this.height); // named constuctor Robot.origin(){ codeName = "Demo-00"; height = 150; } // named constuctor with parameter Robot.extra(this.codeName, this.height, this.talkable); // Redirecting constructors Robot.smart(String codeName):this(codeName, 150); void walking(){ // เดินได้ print("Walking..."); } void talking(){ // พูดคุยได้ print("Talking..."); } }
หวังว่าเนื้อหาเกี่ยวกับการใช้งาน class ในภาษา Dart เบื้องต้น จะเป็นแนวทางสำหรับทบทวน ทำความเข้าใจ และนำไปประยุกต์ใช้งาน
ต่อไป สำหรับการใช้งาน class ยังมีส่วนที่เกี่ยวข้องต่างๆ อีก จะได้นำเสนอในลำดับต่อๆ ไป
เพิ่มเติมเนื้อหา ครั้งที่ 1 วันที่ 21-11-2019
Factory constructor
ในภาษา Dart ยังรอบรับการใช้งาน factory constructor ซึ่งสามารถจะ return ค่ากลับมาเป็น subtype หรือ null ได้ สามารถกำหนด
และใช้งาน factory constructor โดยการใช้งาน "factory" keyword
ทำความเข้าใจคำว่า subtype ดังนี้
void main() { var a = A(); // สร้าง object print(a.runtimeType); // output: A var b = B(); print(b.runtimeType); // output: B } class A{ // default constructor A(); } class B extends A{} class C extends A{}
จากตัวอย่างข้างต้น เมื่อเราสร้าง object จาก class A เราก็จะได้ type เป็น A และถ้าเราสร้าง object จาก class B เราก็จะได้ type
เป็น B เนื่้องจาก class B สืบทอดมาจาก class A อีกที ดังนั้น type B จึงเป็น subtype ของ type A เช่นเดียวกันกับ type C ก็เป้น
subtype ของ A
กลับมาที่นิยามของ factory constructor ซึ่งบอกว่า สามารถ return ค่าเป็น subtype หรือ null ได้ นั่นก็แสดงว่า เมื่อเราทำการ
สร้าง object จาก class A ก็สามารถ ที่จะได้ค่าเป็น type B หรือ type C หรือ null ได้ เมื่อมีการใช้งาน factory contructor
ตัวอย่าง factory constructor ที่ return ค่าเป็น subtype B
void main() { var a = A(); // สร้าง object print(a.runtimeType); // output: A // จะได้ b เป็น instance ของ subtype เท่ากับ B var b = A.name1(); // สร้าง object print(b.runtimeType); // output: B } class A{ // default constructor A(); // factory constructor factory A.name1(){ return B(); } } class B extends A{} class C extends A{}
เพื่อให้เห็นภาพชัดเจนขึ้น เรามาดู Shape class ที่สามารถสร้าง object แล้วคืนค่า เป็น subtype ตามชนิดประเภท type ที่ต้องการได้
void main() { var shape1 = Shape(); // สร้าง object print(shape1.runtimeType); // output: Shape // จะได้ shape2 เป็น instance ของ subtype เท่ากับ Circle var shape2 = Shape.fromTypeName("circle"); // สร้าง object print(shape2.runtimeType); // output: Circle // จะได้ shape3 เป็น instance ของ subtype เท่ากับ Square var shape3 = Shape.fromTypeName("square"); // สร้าง object print(shape3.runtimeType); // output: Square // จะได้ shape4 มีค่าเป็น null var shape4 = Shape.fromTypeName("triangle"); // สร้าง object print(shape4.runtimeType); // output: I don't recognize triangle // output: null } class Shape { Shape(); // default constructor // factory constructor ไม่สามารถใช้ this ในนี้ได้ factory Shape.fromTypeName(String typeName) { if (typeName == 'square') return Square(); if (typeName == 'circle') return Circle(); print('I don\'t recognize $typeName'); return null; } } class Square extends Shape {} class Circle extends Shape {}
จากโค้ด ทั้ง Square และ Circle ล้วนเป็น subtype ของ Shape เนื่องจากมีการสืบทอดจากมาก Shape class และเมื่อเรามีการใช้งาน
factory constructor ที่ให้สามารถกำหนด type ที่ต้องการใช้งาน ได้ และคืนค่าเป็น type ที่ระบุ หรือคืนค่าเป็น null หาก ค่าที่ระบุไม่ตรง
กับที่ได้กำหนดไว้
เราไม่สามารถ return type ที่ไม่เป็น subtype ของ Shape ได้ สมมติเช่น เรามี Triangle class ดังนี้
class Shape { Shape(); // default constructor // factory constructor ไม่สามารถใช้ this ในนี้ได้ factory Shape.fromTypeName(String typeName) { if (typeName == 'square') return Square(); if (typeName == 'circle') return Circle(); // if (typeName == 'triangle') return Triangle(); // error print('I don\'t recognize $typeName'); return null; } } class Square extends Shape {} class Circle extends Shape {} class Triangle{}
เราอาจกล่าวได้ว่า factory constructor มักใช้ในกรณีที่ไม่ต้องการสร้าง instance object จาก class นั้นๆ แต่อาจจะต้องการใช้งาน
subtype เพิ่มสร้าง instance object จาก class ลูกอีกที เป็นต้น
Const constructor
ในกรณีเรามีการใช้งาน object ที่จะไม่มีการเปลี่ยนแปลงใดๆ เกิดขึ้น เราสามารถกำหนดให้ object นั้นๆ เป็น constant หรือค่าที่ไม่
เปลี่ยนแปลง โดยใช้งาน const constructor พร้อมกับกำหนด ตัวแปร instance variable เป็น final ดังตัวอย่างการใช้งานต่อไปนี้
void main() { // ทดสอบแสดงค่า static variable print(ImmutablePoint.origin); // output: Instance of 'ImmutablePoint' // สร้าง object ที่ไม่สามารถแก้ไขค่าได้ var a = ImmutablePoint(100,200); print(a.x); // output: 100 // error ไม่สามารถแก้ไขค่าได้ // a.y = 500; } // class จุดพักัดที่ไม่สามารถเปลี่ยนแปลงได้ class ImmutablePoint { // const constructor const ImmutablePoint(this.x, this.y); // ระบุ final ให้กับ instance variable final int x; final int y; // ใช้งาน static variable static const ImmutablePoint origin = ImmutablePoint(0, 0); // รูปแบบของบรรทัดด้านบนคือ // [static variable] [แบบค่าคงที่่ const] [ชนิดข้อมูล ImmutablePoint] // [ชื่อตัวแปร origin] = [การสร้าง object ด้วยคำสั่ง ImmutablePoint(0, 0)] }
กด Like หรือ Share เป็นกำลังใจ ให้มีบทความใหม่ๆ เรื่อยๆ น่ะครับ

อ่านต่อที่บทความ
-
14 Oct2019การใช้งาน Getter Setter และ Private Variable ในภาษา Dart อ่าน 9,090
เนื้อหาต่อไปนี้ เราจะอยู่ในโหมดของ OOP ในภาษา Dart ต่อจากตอนที่แล้ว
เนื้อหาที่เกี่ยวข้อง
-
17 Sep2019เรียนรู้การเขียนโปรแกรมและใช้งานโปรแกรมภาษา Dart เบื้องต้น อ่าน 6,526
Dart คือ ภาษาโปรแกรมที่พัฒนาโดย Google ถูกนำมาใช้สำหรับสร้างโปรแกรมหรือ Apps&
-
28 Sep2019ประเภทข้อมูล และใช้งานตัวแปร Variable ในภาษา Dart เบื้องต้น อ่าน 10,131
เนื้อหาต่อไปนี้ เราจะมาดูเกี่ยวกับ ตัวแปรในภาษา Dart จากตอนที่แล้ว เราได้
-
02 Oct2019การใช้คำสั่งควบคุมการทำงานของโปรแกรม ในภาษา Dart เบื้องต้น อ่าน 9,146
ในการเขียนโปรแกรมภาษาใดๆ ก็ตาม เราต้องเจอกับเงื่อนไข การทำงาน และต้องกำหน
-
03 Oct2019การกำหนดและใช้งาน Function ในภาษา Dart เบื้องต้น อ่าน 6,843
เนื่องจาก Dart เป็นภาษาโปรแกรมเชิงวัตถุ ทุกอย่างล้วนเป็น Object รวมถึงฟัง
-
กำลังอ่านเนื้อหานี้อยู่04 Oct2019การใช้งาน Class กับโปรแกรมเชิงวัตถุ OOP ในภาษา Dart เบื้องต้น อ่าน 6,928
ในเนื้อหาในตอนต่อไปนี้ เราจะมาดูเกี่ยวกับการใช้งาน class เบื้องต้นในภาษา Dart
-
14 Oct2019การใช้งาน Getter Setter และ Private Variable ในภาษา Dart อ่าน 9,090
เนื้อหาต่อไปนี้ เราจะอยู่ในโหมดของ OOP ในภาษา Dart ต่อจากตอนที่แล้ว
URL สำหรับอ้างอิง
Top
Copy
ขอบคุณทุกการสนับสนุน
![]()