ประเภทข้อมูล และใช้งานตัวแปร Variable ในภาษา Dart เบื้องต้น

เขียนเมื่อ 5 ปีก่อน โดย Ninenik Narkdee
ประเภทตัวแปร variables dart

คำสั่ง การ กำหนด รูปแบบ ตัวอย่าง เทคนิค ลูกเล่น การประยุกต์ การใช้งาน เกี่ยวกับ ประเภทตัวแปร variables dart

ดูแล้ว 14,637 ครั้ง




เนื้อหาต่อไปนี้ เราจะมาดูเกี่ยวกับ ตัวแปรในภาษา Dart
จากตอนที่แล้ว เราได้รู้จักภาษา Dart ในส่วนต่างๆ แบบพอสังเขปไปแล้ว
    เราจะมาลงรายละเอียดเพิ่มเติมเล้กน้อย เพื่อทำความเข้าใจเกี่ยวกับแต่ละ
ส่วน ในเนื้อหานี้เราจะมาในส่วนของตัวแปร Variable ในภาษา Dart
 
สามารถทดสอบการเขียนโปรแกรมผ่านเว็บไซต์ DartPad 

 

การประกาศตัวแปร Variable Declaration

    รูปแบบการประกาศตัวแปรอย่างง่าย สามารถกำหนดโดยใช้ var ตามด้วยชื่อตัวแปร ดังนี้
 

var name1; // การประกาศตัวแปรแบบไม่กำหนดค่าเริ่มต้น 
var name2 = 'Ebiwayo'; // ประกาศตัวแปรพร้อมกำหนดค่า
ตัวแปร name1 ที่ประกาศและไม่ได้กำหนดค่า จะมีค่าเท่ากับ Null
* ตัวแปรใดๆ ที่ประกาศใช้งานและไม่ได้กำหนดค่า จะมีค่าเริ่มต้นเป็น Null
ตัวแปรที่กำหนดค่า ข้างต้น ตัวแปร name2 ทำหน้าที่เก็บประเภทข้อมูลที่เป็น String object โดยมีค่าเท่ากับ 'Ebiwayo'

void main (){

  var name1; // การประกาศตัวแปรแบบไม่กำหนดค่าเริ่มต้น 
  var name2 = 'Ebiwayo'; // ประกาศตัวแปรพร้อมกำหนดค่า
// ตรวจสอบประเภทข้อมูล
  print(name1.runtimeType); // null
  print(name2.runtimeType); // String

}
    การกำหนดตัวแปรโดยใช้ var ประเภทของตัวแปร จะแปรผันไปตามข้อมูล อย่างกรณีข้างต้น เรากำหนดข้อมูลเป้น
ข้อความ 'Ebiwayo' เราก็จะได้ตัวแปรที่เป็น String   ลองกำหนดข้อมูลให้แตกต่างกันดังนี้

void main (){
  var name = 'Ebiwayo';
  var age = 25;
  var weight = 48.5;
  var graduated = true;
  
  print(name.runtimeType); // String
  print(age.runtimeType); // int
  print(weight.runtimeType); // double
  print(graduated.runtimeType); // bool

}
    นอกจากการกำหนดตัวแปรโดยใช้ var แล้ว เราสามารถกำหนดตัวแปรโดยระบุประเภทของข้อมูลแบบเจาะจงได้
โดยใช้ keyword เหล่านี้แทน เช่น String, int, double, bool เป็นต้น

  String name = 'Ebiwayo'; // ข้อความ
  int age = 25; // เลขจำนวนเต็ม หรือเลขฐานอื่นๆ
  double weight = 48.5;  // เลขทศนิยม ใน dart จะไม่มีข้อมูลรูปแบบ float
  bool graduated = true;  // ข้อมูล Boolean
การใช้งาน keyword เพื่อระบุประเภทของข้อมูล จะทำให้เวลาเรากำหนดค่าของตัวแปร ไม่ตรงตามประเภทข้อมูลก็จะขึ้นเตือน
ข้อผิดพลาด ป้องกันการใช้ค่าข้อมูลที่ตรงกับประเภทที่กำหนด
    นอกจากนั้นเรายังสามารถใช้ Object หรือ dynamic สำหรับกำหนดตัวแปร ที่ไม่จำกัดประเภทของตัวแปรไว้แค่ประเภทเดียวเได้
ในรายละเอียดการใช้งาน จะได้กล่าวในลำดับต่อๆ ไป ดูตัวอย่งางการกำหนดโดยใช้ dynamic ดังนี้

  dynamic name = 'Ebiwayo'; 
   ข้อควรจำ: 
        ทุกสิ่งใน Dart ล้วนเป็น Object เสมอ
        ตัวแปรที่ไม่ได้กำหนดค่า จะมีค่าเริ่มต้นเป็น null
 
 
 

การใช้งาน Final และ Const

    ในการกำหนดตัวแปร หากเราไม่ต้องการจะเปลี่ยนแปลงค่าของตัวแปรนั้น เราสามารถใช้ final หรือ const แทน var หรือระบุเพิ่มเติม
กรณีกำหนดประเภทตัวแปร เช่น
 
  final name = 'Ebiwayo'; // var name = 'Ebiwayo';
  const age = 25; // var age = 25;
// หรือ
  final String name = 'Ebiwayo'; // String name = 'Ebiwayo';
  const int age = 25; // int age = 25;
 
    การใช้งาน final และ const มีข้อควรทำความเข้าใจดังนี้ สำหรับ final เราสามารถกำหนดได้เพียงครั้งเดียวและจะถูกเพิ่มเข้าไปใน
หน่วยความจำเมื่อมีการเรียกใช้งานเท่านั้น ในส่วนของ const จะมีมีลักษณะคล้ายกับ final แต่จะถูกเพิ่มเข้าไปในหน่วยความจำทันทีที่
โปรแกรมทำการ compile ถึงแม้เราจะเรียกใช้งานหรือยังไม่เรียกใช้งานก็ตาม
    const ไม่สามารถใช้งานในการกำหนดตัวแปรใน class เหมือน final ทั้งนี้เพราะ ในทุกๆ ครั้งที่เราทำการสร้าง Object จาก class
จะทำให้มีการใช้งานหน่วยความจำในปริมาณมากในการเก็บค่าตัวแปรนั้นแม้จะใช้งานหรือไม่ได้ใช้งาน ต่างจาก final ที่จะถูกเพิ่มไป
ในหน่วยความจำเมื่อมีการใช้งานเท่านั้น อย่างไรก็ตาม เราสามารถใช้ static keyword ร่วมกับ const เพื่อแก้ปัญหานี้ ทำให้สามารถ
เรียกใช้งาน const ภายใน class ได้โดยจะทำการเพิ่มตัวแปรเข้าไปในหน่วยความจำเพียงครั้งเดียวเท่านั้น
 
void main (){
  final name = 'Ebiwayo';
  const PI = 3.14;
  // name = 'Zabi'; // ไม่สามารถแก้ไขค่าตัวแปร final ได้ บรรทัดนี้ error
  print(name); // ค่า final [ Ebiwayo ]
  print(PI); // ค่า const [ 3.14 ]
  print(Shape.PI); // ค่า static const ใน Shape class [ 3.14 ]
  var shape = Shape();
  print(shape.name); // ค่า final จาก Shape class [ Circle ]
}
class Shape{
  final name = 'Circle';
  // const PI = 3.14; // กำหนดได้เฉพาะ static const ใน class
  static const PI = 3.14; // แก้ไขโดยใช้ static keyword
  // static keyword เป็นการบอกว่าให้เพิ่มไปในหน่วนความจำแค่ครั้งเดียว
}
 
    นอกจากเราจะใช้ const สำหรับประกาศตัวแปร constant แล้ว เรายังสามารถใชในการกำหนด constant value ได้อีกด้วย
ตัวอย่างเช่น 

var fruit = const [];
final book = const [];
const fish = []; // เราสามารถตัด const หน้า value ได้ ซึ่งมีค่าเท่ากับ const [];
    ตัวอย่างข้างต้น เราสามารถเปลี่ยนแปลงค่าตัวแปร fruit ที่ไม่ใช่ตัวแปร final และ const ได้ แม้ค่าของตัวแปรจะเป็น constant

fruit = ['apple', 'banana', 'orange']; // เป็น constant value 
    เราจะได้ศึกษาเกี่ยวกับ constant value ในหัวข้อตัวแปร Lists , Map และ Class
 
 
 

ประเภทตัวแปร Built-in 

    ในภาษา Dart จะมีประเภทของตัวแปรเฉพาะมาด้วยกันดังนี้
    - numbers ชนิดข้อมูลที่เป็นตัวเลข
    - strings ชนิดข้อมูลที่เป็นข้อความ
    - booleans ชนิดข้อมูลที่เป้น true หรือ false
    - lists ชนิดข้อมูลที่เป็น array โดยมี key เป็นตัวเลขเรียงเป็นลำดับ เป็น base zero หรือเริ่มต้นที่ 0 
    - set ชนิดข้อมูลที่เป็นกลุ่มของ object ที่ไม่ได้เรียงลำดับใดๆ และมีค่าไม่ซ้ำกัน
    - maps ชนิดข้อมูลที่เป็น object โดยมาเป็นชุดข้อมูลที่มี key และ value จับคุู่กัน 
    - Runes
    - symbols 
 
    สำหรับ 2 ประเภทหลัง เราอาจจะไม่จำเป็นต้องสนใจในตอนนี้   มาดูตัวอย่างแต่ละประเภทเพื่อให้เห็นภาพ
 
void main (){
  var name = 'Ebiwayo';
  var age = 24;
  var graduated = true;
  var hobby = ['Reading', 'Jogging', 'Shopping'];
  var sport = {'tennis', 'golf', 'swimming'};
  var address = {
    'city': ['Bangkok'],
    'country': 'Thailand'
  };
  print(name.runtimeType); // String
  print(age.runtimeType); // int
  print(graduated.runtimeType); // bool
  print(hobby.runtimeType); // List<String> 
  print(sport.runtimeType); // Set<String>
  print(address.runtimeType); // Map<String, Object>
}
 
    เมื่อเรากำหนดตัวแปรโดยใช้ var เราสามารถเลือกที่จะให้ตัวแปรนั้น เป็นข้อมูลประเภทใดๆ ก็ได้ตามต้องการ เช่น หากเรากำหนด
เป็นค่าเป็นตัวเลข ตัวแปรนั้นๆ ก็จะเป็นประเภท number  หรือเรากำหนดค่าตัวแปรใดๆ เป้น true หรือ false  ประเภทของตัวแปรนั้นๆ
ก็จะเป็น booleans เหล่านี้เป็นต้น
    สำหรับตัวแปรทุกตัวในภาษา Dart จะเป็น object เช่น เราตัวแปรที่ข้อความ ก็คือ String object เป็นต้น  ดังนั้นเราสามารถที่จะกำหนด
ค่าโดยใช้ constructor อย่างเช่นประเภทข้อมูลที่เป็น maps เราสามารถกำหนดโดยใช้ constructor ของตัวมันเองเป็นดังนี้แทนได้
 
//   var address = {
//     'city': ['Bangkok'],
//     'country': 'Thailand'
//   };
  // กรณีกำหนดตัวแปร address โดยใช้ constructor 
  var address = Map();
  address['city'] = 'Bangkok';
  address['country'] = 'Thailand';
 
    เราจะมาดูในแต่ละประเภทเพิ่มเติมตามลำดับ
 
 

Numbers 

    สำหรับประเภทข้อมูลที่เป็นตัวเลข ใน Dart จะใช้ keyword 2 ตัวคือ int และ double
    int เป็นตัวเลขจำนวนเต็ม 
    dobule เป็นตัวเลขทศนิยม
    โดยทั้ง int และ double จะเป็นประเภทข้อมูลย่อยของ num อีกที ประเภทข้อมูลตัวเลข จะรองรับการดำเนินการทางคณิตศาสตร์ต่างๆ
ไม่ว่าจะเป็น +,-,* หรือ /  สามารถใช้งาน method เช่น abs() , cell() และ floor() เกี่ยวกับแปลงเป็นเลขจำนวนเต็มบวก การปัดเศษขึ้นหรือ
ปัดเศษลง  นอกจากคำสั่งต่างๆ แล้วใน Dart ยังมี dart:math library สำหรับช่วยจัดการเกี่ยวกับการดำเนินการทางคณิตศาสตร์ได้อีกด้วย
 
    สำหรับ int หรือเลขจำนวนเต็ม คือตัวเลขที่ไม่มี ทศนิยม อาจจะเป็นตัวเลขฐาน 10 ทั่วไปหรือเลขฐานอื่นๆ ก็ได้เช่น

var x = 24;
var hex = 0xDEADBEEF;
    การกำหนดตัวแปรตัวเลขโดยใช้ var หากค่าของตัวแปรมีทศนิยม ตัวแปรนั้นจะเป็น double 
    แต่หากกำหนดเป็น int แล้วให้ค่ามี เลขทศนิยม ก็จะขึ้น error

var y = 1.1; // ตัวแปร y เป็น double
var exponents = 1.42e5; // ตัวแปร exponents เป็น double

// error - 
// A value of type 'double' can't be assigned to a variable of type 'int'.
  int height = 170.0;  // จะต้องไม่มีทศนิยม

  // กรณีนี้ไม่ error ตัวแปรที่เป็น double ไม่มีเลขทศนิยมได้
  double z = 1; // มีค่าเท่ากับ double z = 1.0.
  print(z); // เท่ากับ 1
  
  double pi = 22/7;
  print(pi); // 3.142857142857143
  // แสดงเลขหลังทศนิยม 3 ตำแหน่ง หากไม่มีทศนิยม จะเป็น .000
  print(pi.toStringAsFixed(3)); // ทศนิยม 3 ตำแหน่ง 3.143
  print(pi.toInt()); // เป็นจำนวนเต็ม เท่ากับ 3
  // แสดงเลขหลังจำนวนเต็ม รวมจุดด้วย หากไม่มี จะเป็น .00
  print(pi.toStringAsPrecision(3)); //3.14
    การใช้คำสั่ง toString() , toStringAsFixed() , toStringAsPrecision() เป็นการแปลงประเภทของข้อมูลจาก int หรือ double 
เป็นข้อความ string   ตรงกันข้าม หากเราต้องการแปลงข้อความที่เป็นตัวเลข ให้เป็น int หรือ double สามารถใช้คำสั่ง parse() ดังนี้
 
  // String -> int
  var one = int.parse('1');
  // String -> double
  var onePointOne = double.parse('1.1');  
  // รูปแบบ double.parse('ข้อความตัวเลข');
  // จากคำสั่งข้างต้น เราจะได้ตัวแปร one = 1; และ onePointOne = 1.1;
 
 
 

Strings

    การกำหนดค่าตัวแปรเป็นข้อความ String ในภาษา Dart สามารถใช้ single / double qoute ในการสร้างข้อความ สามารถใช้ var 
สำหรับประกาศตัวแปร หรือใช้ String หากต้องการระบุเจาะจง 
 
void main (){
  var s1 = 'Single quotes work well for string literals.';
  var s2 = "Double quotes work just as well.";
  String s3 = 'It\'s easy to escape the string delimiter.';
  String s4 = "It's even easier to use the other delimiter.";
  
  // ตัวแปร s3 กรณี เครื่องหมาย apostrophes ('s) เมื่อใช้งานร่วมกับ single qoute
  // ให้เพิ่มเครืองหมาย \ ไว้ด้านหน้า ' เพื่อให้ตัวโปรแกรมมองว่า ' 
  // เป็นข้อความปกติไม่ใช้สัญลักษณ์ในโปรแกรม หรือสามารถใช้สัญลักษณ์เป็น double qoute แทน
  // เหมือนตัวแปร s4 
}
 
    การแทรกค่าตัวแปร เพื่อให้แสดงรวมในข้อความ สามารถใช้รูปแบบ ${expression} เมื่อ expression คือนิพจน์ ตัวแปร หรือการดำเนิน
การของตัวแปรภาย หรือกรณี expression เป็นค่าตัวแปรที่ระบุชัดเจน เราสามารถใช้เป็นชื่อตัวแปรแทนเป็น $variable_name ได้

void main (){
  var name = 'Ebiwayo';
  
  var greeting_msg = 'Hi ${name}!'; // หรือใช้เป็น $name แทนได้
  print(greeting_msg); // Hi Ebiwayo!
  
  // บางครั้งเราอาจจะคุ้นกับการต่อข้อความด้วยเครื่องหมาย + 
  // ดูแนวทางการใช้งานรูปแบบต่างๆ 
  // 'Hi ${name}!'
  // 'Hi $name!'
  // 'Hi '+name+'!'
  
}
    การต่อข้อความ กรณีที่เราต้องการแสดงข้อความยาวๆ แต่ไม่ต้องการให้โค้ดยาวออกไปด้านข้าง สามารถใช้การขึ้นบรรทัดใหม่
โดยจะมีเครื่องหมาย + ต่อท้ายแต่ละข้อความด้วยหรือไม่ก็ได้
    การต่อข้อความพร้อมแสดงแบบขึ้นบรรทัดใหม่ สามารถใช้เครื่องหมาย single qoute หรือ double qoute ติดกันสามตัวสำหรับ
เปิดปิดข้อความที่ต้องการได้ ดังตัวอย่างด้านล่าง

void main (){
  var name = 'Ebiwayo';
  
  // แบบใช้เครื่องหมาย +  ผลลัพธ์ไมได้เป็นการขึ้นบรรทัดใหม่
  var greeting_msg = 'Hi ${name}! ' +
                      'Long time no see.'; 
  print(greeting_msg); // Hi Ebiwayo! Long time no see.
  
  // แบบไม่มีเครื่องหมาย + ก็ได้  ผลลัพธ์ไมได้เป็นการขึ้นบรรทัดใหม่
  var greeting_msg = 'Hi ${name}!' 
                      'Long time no see.'; 
  print(greeting_msg); // Hi Ebiwayo! Long time no see.
 
// แบบขึ้นบรรทัดใหม่  ใช้ \n
  var greeting_msg = 'Hi ${name}! \n' 
                      'Long time no see.'; 
  print(greeting_msg); 
  // Hi Ebiwayo! 
  // Long time no see.
  
//  แบบขึ้นบรรทัดใหม่ ใช้ ''' หรือ """
  var greeting_msg = '''Hi ${name}!  
                      Long time no see.'''; 
  print(greeting_msg); 
  // หรือ
  var greeting_msg = """Hi ${name}!  
                      Long time no see."""; 
  print(greeting_msg);   
  // Hi Ebiwayo! 
  // Long time no see.    
  
}

    การแสดง raw string เราสามารถกำหนดโดย ขึ้นต้นด้วย r ก่อนกำหนดค่าข้อความ raw string ที่ต้องการ
ข้อความ raw string ก็คือข้อความที่ตัวอักษรหรือตัวอักขระ หรือสัญลักษณ์ ที่แสดงค่าของมันเอง โดยไม่มีการประมวล
ผลก่อนแสดงข้อความ อย่างเช่น \n ที่หากเรากำหนดในข้อความปกติ จะถูกประมวลผลเป็น การขึ้นบรรทัดใหม่
แต่หากเราต้องการแสดงค่าตามตัวของมัน เราสามารถกำหนดโดยใช้รูปแบบ raw string แทน 

void main (){
  // A Normal string
  var msg1 = 'Hello! \nNice to meet you.\n';  
  // A Raw String  
  var msg2 = r'Hello! \nNice to meet you.\n';
  print(msg1);
// Hello! 
// Nice to meet you.  
  
  print(msg2);
  // Hello! \nNice to meet you.\n
}
    ข้อความตามตัวอักษรล้วนเป็น const value หรือก็คือค่าคงที่ถูกเก็บในหน่วยความจำทันทีที่มีการใช้งาน เข้าใจอย่างง่าย เช่น
เลข 0 ก็เป็นตัวเลขค่าคงที่ ข้อความ 'Hello' เป็นข้อความค่าคงที่  true ก็เป็น ค่าคงที่ boolearn โดยตัวของมันเอง เหล่านี้เป็นต้น
การกำหนดค่าให้กับตัวแปร cnnstant จะต้องเป็น const value เช่น

// การกำหนดค่าให้กับตัวแปร constant  โดย 0, true และ 'a constant string' ล้วนเป็น const value
const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';

// การกำหนดค่าให้กับ ตัวแปร validConstString โดยใช้รูปแบบ expression หรือนิพจน์
// ค่าตัวแปรที่นำมาแทรก รวมกัน ต้องเป็นค่าจากตัวแปร constant ที่เป็น numeric, string, boolean หรือ null
const validConstString = '$aConstNum $aConstBool $aConstString';
print(validConstString);
// Stirng ผลล้พธ์ที่ได้ '0 true a constant string'
    มาดูตัวอย่างการกำหนดค่าใน expression ที่ไม่ใช้ตัวแปร constant
 

// ไม่สามารถใช้ตัวแปรเหล่านี้ กำหนดค่าใน const string ได้.
var aNum = 0;
var aBool = true;
var aString = 'a string';
const aConstList = [1, 2, 3];

// ใช้ตัวแปรที่ไม่ได้เป็น constant มากำหนดค่าใน expression จะไม่สามารถทำได้
// โค้ดด้านล่าง จะ error
const invalidConstString = '$aNum $aBool $aString $aConstList';

 
 

Lists

    ในภาษา Dart จะเรียกข้อมูลประเภท Array ว่า List object ดังนั้น ถ้าเราคุ้นเคยกับตัวแปร array ในภาษาต่างๆ มาแล้วก็จะมีลักษณะเหมือนกัน
list หรือ array คือกลุ่มของข้อมูลที่มีการเรียงกันเป็นลำดับ

void main (){
  var hobby = ['Reading', 'Jogging', 'Shopping'];
  var list = [1, 2, 3];
  var listMix = [1,'two',3,true];
  print(hobby.runtimeType); // List<String>
  print(list.runtimeType); // List<int>
  print(listMix.runtimeType); // List<Object>
}
    ตัวอย่างข้างต้นเรากำหนดตัวแปร List สามรูปแบบคือ ที่เก็บข้อความอย่างเดียว List<String> ที่เก็บตัวเลขอย่างเดียว List<int> และ
ที่เก็บแบบผสมผสานกันทั้งข้อความ ตัวเลข และ boolean
    รูปแบบที่ 1 และ 2 เรามีการเจาะจงประเภทข้อมูลของสมาชิกค่าเริ่มต้นเหมือนกันหมด คือ เป็นข้อความทั้งหมด หรือเป็นตัวเลขทั้งหมด
ลักษณะแบบนี้ Dart จะมองว่าเป็นข้อมูล List<String> และ List<int> ตามลำดับ  ดังนั้นการเพิ่มข้อมูลใหม่เข้าไป ต้องเป้นประเภทกับ
รูปแบบนั้นๆ หากกำหนดไม่ตรงตามรูปแบบจะเกิด error แจ้งเตือนประเภทข้อมูลไม่ถูกต้อง 
    แตกต่างจากกรณีที่ 3 ข้อมูลเริ่มต้นมีการผสมผสานกันในหลายประเเภทข้อมูล Dart มองเป็น List<Object> ทำให้สามารถเพิ่มข้อมูล
ประเภทต่างๆ เข้าไปได้ โดยไม่เกิด error ขึ้น

void main (){
   // List<String>
  var hobby = ['Reading', 'Jogging', 'Shopping'];
  hobby.add(2);// เกิด error เพิ่มข้อมูลไม่ตรงตามรูปแบบ
  // List<int>
  var list = [1, 2, 3]; 
  list.add('Fishing'); // เกิด error เพิ่มข้อมูลไม่ตรงตามรูปแบบ
  // List<Object>
  var listMix = [1,'two',3,true];
  listMix.add('5'); // ไม่เกิด error 
}
    ใน List จะมี key index เป็น zero-based หรือค่า key เริ่มต้นที่ 0  นั่นคือ ตัวแรกจะมี key เท่ากับ 0 และตัวสุดท้าย จะมีค่า
key เท่ากับ จำนวนของรายการ - 1 หรือก็คือ list.length - 1
    การเรียกดูข้อมูล และการกำหนดและแก้ไขค่า ใช้รูปแบบเดียวกับใน JavaScript คือเรียกตัวแปรพร้อมระบุค่า key ในรูปแบบ 
varName[key] ดูตัวอย่างประกอบ

void main (){
  var hobby = ['Reading', 'Jogging', 'Shopping'];
  print(hobby[0]); // Reading
  print(hobby[hobby.length-1]); // Shopping
  print(hobby[2]); // Shopping
  hobby[1] = 'Fishing'; // กำหนดค่าใหม่ให้กับตัวที่ 2
  print(hobby); // [Reading, Fishing, Shopping]
}
    เราสามารถกำหนด List เป็น constant value โดยระบุ const ไว้ด้านหน้า 

var constantList = const [1, 2, 3];
// ในกรณีเมื่อกำหนดเป็น const value แล้วจะไม่สามารถเปลี่ยนแปลงค่าได้
// constantList[1] = 1; // เกิด error
    เราสามารถเพิ่มรายการเข้าไปใน list ทีละหลายๆค่าพร้อมกัน โดยใช้ spead operator (...) หรือใช้ null-aware spread operator (...?)
กรณีป้องกันการเพิ่มข้อมูลที่เป้นค่า null ดูตัวอย่างประกอบ

void main (){
  var listA = [1, 2, 3];
  var listB = [0, ...listA];
  print(listB); // [0, 1, 2, 3]
  
  var listC;
  var listD = [3, ...?listC]; // ใช้ ...? แทน
 // var listD = [3, ...listC]; // กรณีเมื่อ listC เป็น null จะเกิด error
  print(listD);// [3]
  
  var listE = [2,4];
  var listG = [0, ...listE, 6, 8];
  print(listG);// [0, 2, 4, 6, 8]
}
    ดูแนวทางการใช้งานเพิ่มเติมได้ที่ 
  
    นอกจากนั้น เรายังสามารถใช้งาน collection if และ collection for สำหรับสร้าง list โดยใช้การกำหนดเงื่อนไข และการวนลูป
ทำงานซ้ำ ดูตัวอย่างประกอบ

void main (){
  // collection if
  var promoActive = true;
  var nav = [
    'Home',
    'Furniture',
    'Plants',
    if (promoActive) 'Outlet'
  ];
  // ถ้า promoActive = true
  print(nav); // [Home, Furniture, Plants, Outlet]
  // ถ้า promoActive = false
  print(nav); // [Home, Furniture, Plants]
  
  // collection for
  var listOfInts = [1, 2, 3];
  var listOfStrings = [
    '#0',
    for (var i in listOfInts) '#$i'
  ];  
  print(listOfStrings); // [#0, #1, #2, #3]
  
}
 
 

Sets

    ตัวแปร set ในภาษา Dart คือชุดข้อมูลที่ไม่ซ้ำกันและไม่มี index key ลำดับการจัดเรียงเหมือนตัวแปร list
รูปแบบการกำหนดจะคล้ายกัน แต่ใน set จะใช้เป็นเครื่อง {} ในขณะที่ list จะใช้เป็น []

void main (){

  var set1 = {1, 2, 3, 4};
  var set2 = {'male','female'};
  var set3 = {1,'two',3,'four'};
   
  print(set1.runtimeType);// Dart มองเป็น Set<int>
  print(set2.runtimeType); // Dart มองเป็น Set<String>
  print(set3.runtimeType); // Dart มองเป็น Set<Object>
  
}
    การกำหนดค่าให้กับ set หากค่าเริ่มต้นเป็นตัวแปรประเภทใดประเภทหนึ่งทั้งหมดแล้ว การเพิ่มรายการเข้าไปใหม่ จะต้องเป็น
ประเภทข้อมูลเดียวกันเท่านั้น ไม่เช่นนั้น จะเกิด error ขึ้น อย่างในตัวแปร set1 และ set2 การที่จะเพิ่มค่าใหม่เข้าไป ต้องเป็นตัวเลข
และข้อความ ตามลำดับ  ในขณะที่ตัวแปร set3 เป็นแบบผสมผสานกัน เราสามารถเพิ่มค่าใหม่เป็นประเภทข้อมูลใดๆ ก็ได้
    การกำหนด set ค่าว่าง ต้องระวังความสับสนกับตัวแปร map โดยตัวแปร map จะกำหนดค่าว่างโดยใช้รูปแบบ {} ในขณะที่
set จะมีต้องมีประเภทตัวแปรกำกับด้านหน้าเช่น <String>{} หรือกรณีกำหนดค่าโดยใช้ {} เหมือนตัวแปร map ในกรณีนี้ต้องระบุ
ประเภทตัวแปร Set ให้กับตัวแปรนั้นเสมอ ดูตัวอย่างประกอบ

var names = <String>{}; // การกำหนดตัวแปร Set ค่าว่าง
Set<String> names = {}; // การกำหนดตัวแปร Set ค่าว่างแบบที่ 2
var names = {}; // การกำหนดลักษณะนี้เป็นการกำหนดตัวแปร Map ไม่ใช่ตัวแปร Set
    ตัวอย่างการใช้งานคำสั่งที่เกี่ยวกับตัวแปร Set บางส่วนเบื้องต้น

void main (){

  var set1 = {1, 2, 3, 4};
  var set2 = {'male','female'};
  var set3 = {1,'two',3,'four'};
  var set4 = {'5',6,'seven'};
   
  print(set1.length);// การหาจำนวนรายการใน set 
  // set1.add('5'); // กรณีนี้จะ error เนื่องจากประเภทตัวแปรไม่ตรงกัน
  set1.add(5); // เพิ่ม 5 เข้าไปในตัวแปร set1
  print(set1); // {1, 2, 3, 4, 5}
  set3.addAll(set4); // เพิ่มรายการ set4 ทั้งหมดไปใน set3
  print(set3); // {1, two, 3, four, 5, 6, seven}
  set3.remove('5');
  print(set3); // {1, two, 3, four, 6, seven}
  
}
    ในตัวแปร set ยังรองรับการใช้งาน spead operator (...) เช่นเดียวกับ list อีกด้วย
 
 

Booleans

    ตัวแปร boolean เป็นตัวแปรสำหรับตรวจสอบค่านิพจน์ สมการ หรือเงื่อนไขการเปรียบเทียบข้อมูล มีค่าเป็น true หรือ false ในภาษา
Dart จะใช้ bool สำหรับกำหนดตัวแปรแบบเจาะจงให้กับ boolean ค่าของตัวแปร boolean ทั้ง true และ false เป็น const value หรือ
ค่าที่ถูกกำหนดเข้าไปในหน่วยความจำทันทีที่มีการกำหนดค่าข้อมูล

void main (){
  var graduated = true;
  bool employee = false;
  
  // แนวทางการตรวจสอบ เงื่อนไข เช่น if 
  if(graduated){
    print('You were graduated');
  }
  
  // ตรวจสอบข้อความเป็นค่าว่างหรือไม่ ไม่รวมเว้นวรรค
  var name = ' ';
  if(name.isEmpty){ // มีค่าเท่ากับเงื่อนไข if(name == ''){}
    print('name is Empty');
  }
  // ตรวจสอบเงื่อนไข ค่าเท่ากับ 0 หรือไม่
  var point = 0;
  if(point == 0){
    print('Point is 0');
  }

  // ตรวจสอบค่า null 
  var money; // ตัวแปรทุกตัวที่ไม่กำหนดค่า มีค่าเริ่มต้นเป็น null
  if(money == null){
    print('money is null');
  }
  
}
 
 

Map

    ตัวเปรประเภท map จะเป็น object ที่มี key และ value ทั้ง key และ value จะเป็น object ประเภทใดๆ ก็ได้ แต่ค่า key จะต้องไม่ซ้ำกัน 
ในขณะที่ค่า value สามารถกำหนดซ้ำกันได้ 

  var address = {
    'city':'Bangkok',
    'country':'Thailand'
  };
  var favoriteMovie = {
    1:'Iron man',
    2:'Avenger'
  };
จากตัวอย่างโค้ดข้างต้น Dart จะมองตัวแปร address เป็นตัวแปรประเภท Map<String, String> และตัวแปร favoriteMovie เป็น Map<int, String>
ถ้าหากเราทำการเพิ่มข้อมูลใหม่เข้าไป และไม่เป็นไปตามรูปแบบประเภทของตัวแปรเดิม จะเกิด eroor ขึ้น ตัวอย่างเช่น

  var address = {
    'city':'Bangkok',
    'country':'Thailand'
  };
// address['zipcode'] = 10310; // เกิด error
  address['zipcode'] = '10310'; // ไม่ error  
สังเกตว่า การเพิ่มตัวเลข เข้าไปใน key ที่ชื่อ zipcode จะเกิด error ขึ้น ทั้งนี้เพราะรูปแบบของตัวแปรข้างต้น เป็นแบบ Map<key, value> 
ที่เท่ากับ Map<String, String> ดังนั้น ค่า value จะต้องเป็น string ตามแนวทางการกำหนดค่าที่ถูกต้องในบรรทัดต่อมา
 
ในการกำหนดตัวแปรประเภท Map ข้างต้นยังรองรับการกำหนดโดยใช้งาน Map constructor ดังนี้
 

  var address = Map(); //ใช้งาน Map contructor
  address['city'] = 'Bangkok';
  address['country'] = 'Thailand';

  var favoriteMovie = Map(); //ใช้งาน Map contructor
  favoriteMovie[1] = 'Iron man';
  favoriteMovie[2] = 'Avenger';
 
สำหรับการกำหนดตัวแปรโดยใช้ Map constructor จะทำให้ ประเภทตัวแปรของค่า key และ value จะเป็น dynamic
ในรูปแบบ Map<dynamic, dynamic> ซึ่งข้อมูลที่เป็นแบบ dynamic นั้นสามารถปรับเปลี่ยนประเภทตัวแปรได้ตลอดเวลา
ขึ้นกับค่าข้อมูลที่กำหนด ดังนั้น หากเรากำหนดเพิ่มค่าใหม่ ไม่ตรงกับรูปแบบเดิม ก็จะไม่เกิด error ขึ้น  สมมติเช่นตัวแปร
address ในกรณีนี้เราสามารถเพิ่ม key เป็น zipcode และ value เป็นตัวเลข 10310 ดังนี้ได้

  var address = Map(); //ใช้งาน Map contructor
  address['city'] = 'Bangkok';
  address['country'] = 'Thailand';
  // การเพิ่มค่าใหม่ 
  address['zipcode'] = 10310;  // ไม่ error เนื่องจาก เป็น Map<dynamic, dynamiic>
ดูรูปแบบการใช้งานเกี่ยวกับ map เพิ่มติม ตามตัวอย่างด้านล่าง
 

  var address = Map(); //ใช้งาน Map contructor
  address['city'] = 'Bangkok';
  address['country'] = 'Thailand';

  // การเพิ่มค่าใหม่ 
  address['zipcode'] = 10310; 

  // แสดงค่าของตัวแปร map โดยเรียกตัวแปรและกำหนด key ที่จะแสดง
  // address['country']
  print(address['country']); // Thailand

  // หากเรียกข้อมูลตัวแปร โดยระบุ key ที่ไม่ได้กำหนด จะได้ค่าเป็น null
  print(address['countryCode']); // null

  print(address.length); // จำนวน key-value ทั้งหมด ตัวอย่างนี้คือ 3
  // การค่า key และ value ในตัวแปร map ว่ามีค่าตรงตามที่กำหนดหรือไม่ true | false
  // การกำหนดค่าสำหรับค้นหา เป็นแบบ case sensitive และต้องเป็นประเภทข้อมูลเหมือนกัน
  // เช่น ค้นตัวเลข หากกำหนด '10310' กับ 10310 จะได้ผลลัพธ์ไม่ได้เหมือนกัน
  print(address.containsValue('Thailand')); // true
  print(address.containsKey('Country'));  // false
  
  address.isEmpty; // ตรวจสอบว่าไม่มีข้อมูลหรือไม่ true | false
  address.isNotEmpty; // ตรวจสอบว่ามีข้อมูลหรือไม่ true | false
  address.remove('zipcode'); // ลบรายการที่มี key เท่ากับ zipcode
  address.clear(); // ล้างค่าทั้งหมด
  
  // วนลูปแสดงข้อมูลใน map
  address.forEach((key, value){
    print(key);
    print(value);
  });
 
    ยังมีรูปแบบคำสั่งที่สามารถใช้งานกับ map เพิ่มเติม จะได้นำมาเป็นข้อมูลในลำดับต่อๆ ไป


   เพิ่มเติมเนื้อหา ครั้งที่ 1 วันที่ 26-11-2019


รู้จักกับ Generics

    การใช้งาน Generics

    ถ้าเราสังเกตการใช้งานตัวแปร List จะเห็นว่ามีการกำหนด ในรูปแบบ List<E>  โดยที่เครื่องหมาย <..> (ปีกกาสามเหลี่ยม) จะแสดงถึง
การใช้งาน generic หรือที่เรียกว่าพารามิเตอร์ชนิดข้อมูล (type parameter) และเพื่อความสะดวกในการกำหนดใช้งาน ก็จะใช้เป็นตัว
อักษรตัวเดียวเช่น E, T, S, K หรือ V ตัวอย่างเช่น
 
    E ใช้สำหรับ element type ของชุดข้อมูล array 
 
class IterableBase<E> {}
class List<E> {}
class HashSet<E> {}
class RedBlackTree<E> {}
 
    K และ V ใช้สำหรับ key และ value ที่มีความเชื่อมโยงสัมพันธ์ของข้อมูล
 
class Map<K, V> {}
class Multimap<K, V> {}
class MapEntry<K, V> {}
    R ใช้สำหรับข้อมูลที่เป็นการ return ค่าที่ได้จากฟังก์ชั่น หรือ class  โดยทั่วไปแล้วจะไม่ค่อยเห็นใช้งานเท่าไหร่
 
abstract class ExpressionVisitor<R> {
  R visitBinary(BinaryExpression node);
  R visitLiteral(LiteralExpression node);
  R visitUnary(UnaryExpression node);
}
 
    ในส่วนของ T, S และ U จะใช้สำหรับ generics ที่มีการใช้งาน type parameter เดียว และครอบการใช้งาน generics ด้านในไว้อีกที 
กรณีนี้เราสามารถใช้ตัวอักษรอื่นๆ ด้านในแทน เพื่อไม่ให้เกิดการซ้อนทับกันหรือสับสนได้ 
 
class Future<T> {
  Future<S> then<S>(FutureOr<S> onValue(T value)) => ...
}
   จะเห็นว่าใน generic method then<S> ใช้ตัว S เพื่อเลี้ยงการทับซ้อนของการใช้งานตัว T ใน Future<T>
 
    สำหรับกรณีอื่นๆ ที่ไม่ได้เป็นไปตามเงื่อนไขหรือรูปแบบข้างต้น เรายังสามารถใช้ตัวอักษรแรกของชื่อที่ใช้สำหรับช่วยจำหรือ จะใช้
เป็นชื่อขยายเต็มแทนก็ได้ เช่น
 
// แบบใช้ตัวแรกของคำที่ใช้
class Graph<N, E> {
  final List<N> nodes = [];
  final List<E> edges = [];
}

// หรือแบบที่ใช้ชื่อเต็ม
class Graph<Node, Edge> {
  final List<Node> nodes = [];
  final List<Edge> edges = [];
}
 

    ประโยชน์ของการใช้งาน Generics

    Generics ถูกใช้งานบ่อยในกรณีที่ต้องการความถูกต้องของชนิดข้อมูลที่นำไปใช้งาน ซึ่งเมื่อความถูกต้องของข้อมูลที่ป้อนมีความถูกต้อง
ชัดเจน ผลลัพธ์ที่ได้ ก็จะมีความถูกต้องตามไปด้วย รวมถึงการทำงานโดยรวมก็เป็นไปด้วยดี เรายังสามารถใช้งาน generic ในการช่วยลด
การกำหนดโค้ดที่ใช้งานซ้ำกันได้
    ตัวอย่างเช่น สมมติเราต้องการกำหนดตัวแปร List ที่เป็นข้อมูล String อย่างเดียว เราก็จะกำหนดในรูปแบบ List<String>
 
var names = List<String>();
names.addAll(['Seth', 'Kathy', 'Lars']); // รูปแบบข้อมูลถูกต้อง เพิ่มรายการได้ปกติ
names.add(42); // Error เพราะรูปแบบข้อมูลไม่ถูกต้อง
    หากกำหนดข้อมูลไม่ตรงตาม type parameter หรือรูปแบบการใช้งาน generic ก็จะเกิด error ขึ้น 
 
    ต่อไปดูกรณี ในการช่วยลดการเขียนโค้ดซ้ำ โดยการใช้งาน generic  สมมติว่าเราต้องการเขียนโค้ดเพื่อทำการ cache ข้อมูลหรือ object
ใดๆ  โดยทำการสร้าง interface ในรูปแบบดังนี้
 
abstract class ObjectCache {
  Object getByKey(String key);
  void setByKey(String key, Object value);
}
    จากนั้น เราพบว่า ต้องมีการ cache สำหรับ ข้อมูล String  ซึ่งเราก็อาจจะสร้าง interface ในลักษณะคล้ายๆ กันดังนี้
 
abstract class StringCache {
  String getByKey(String key);
  void setByKey(String key, String value);
}
    ต่อมาเราก็อย่างจะสร้างการ cache สำหรับข้อมูล ตัวเลข เราก็ทำคล้ายๆ กับรูปแบบของ string 
    ถ้าสังเกตให้ดี เราจะเห็นว่า ส่วนที่มีการเปลี่ยนแปลงของการกำหนด interface ข้างต้น ก็คือ type หรือชนิดของข้อมูลที่แตกต่างกัน จึง
เป็นที่มาของการใช้งาน generics หรือที่เรียกว่า type parameter  โดยแทนที่เราจะเขียน interface แยกแต่ละชนิดข้อมูล เราก็จะใช้งาน
type parameter เป็นดังนี้แทนได้
 
abstract class Cache<T> {
  T getByKey(String key);
  void setByKey(String key, T value);
}
    ในโค้ดข้างต้น T ก็คือ type หรือชนิดข้อมูลที่เราต้องการส่งเป็น parameter เข้าไป  ซึ่งจะเป็นอะไรก็ได้ ที่สามารถกำหนดหรือระบุทีหลังได้


กด Like หรือ Share เป็นกำลังใจ ให้มีบทความใหม่ๆ เรื่อยๆ น่ะครับ



อ่านต่อที่บทความ









เนื้อหาที่เกี่ยวข้อง









URL สำหรับอ้างอิง





คำแนะนำ และการใช้งาน

สมาชิก กรุณา ล็อกอินเข้าระบบ เพื่อตั้งคำถามใหม่ หรือ ตอบคำถาม สมาชิกใหม่ สมัครสมาชิกได้ที่ สมัครสมาชิก


  • ถาม-ตอบ กรุณา ล็อกอินเข้าระบบ
  • เปลี่ยน


    ( หรือ เข้าใช้งานผ่าน Social Login )







เว็บไซต์ของเราให้บริการเนื้อหาบทความสำหรับนักพัฒนา โดยพึ่งพารายได้เล็กน้อยจากการแสดงโฆษณา โปรดสนับสนุนเว็บไซต์ของเราด้วยการปิดการใช้งานตัวปิดกั้นโฆษณา (Disable Ads Blocker) ขอบคุณครับ