ในเนื้อหาในตอนต่อไปนี้ เราจะมาดูเกี่ยวกับการใช้งาน 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 ยังมีส่วนที่เกี่ยวข้องต่างๆ อีก จะได้นำเสนอในลำดับต่อๆ ไป