3

Bài 2. Biến và các kiểu dữ liệu trong Dart

Biến và các kiểu dữ liệu trong Dart

OK, như vậy là trong Bài 1. Cấu trúc một chương trình Flutter/Dart, các bạn đã biết sơ qua về cấu trúc và cách chạy (biên dịch) một chương trình viết bằng Dart/Flutter.

Tuy nhiên, một chương trình tin học thông thường gồm rất nhiều câu lệnh xử lý trên dữ liệu (dữ liệu do người dùng nhập vào, dữ liệu tự sinh ra trong quá trình tính toán, dữ liệu lấy từ các tệp trên máy tính….) Và để làm việc (tính toán, xử lý) dữ liệu đó, chúng ta cần đến các biến để lưu trữ chúng.

1. Khai báo biến trong chương trình Dart

1.1. Cú pháp khai báo biến trong Dart

Để khai báo một biến trong chương trình, chúng ta sử dụng cú pháp:

var tên_biến;hoặc kiểu_dữ_liệu_của_biến tên_biến;

Trong các phiên bản cũ, khi khai báo theo cách trên, Dart sẽ gán cho các biến một giá trị mặc định là null. Bắt đầu từ phiên bản 2.0, Dart/Flutter chính thức hỗ trợ null safety, nên sẽ không gán giá trị mặc định null nữa mà bạn bắt buộc phải cho biến một giá trị trước khi sử dụng. Do đó, thông thường chúng ta sẽ khai báo biến như sau:

var tên_biến = giá_trị;hoặc kiểu_dữ_liệu_của_biến tên_biến = giá_trị;

Ví dụ

void main() {
  var name = 'Phuong';
  int age = 30;
}

Nếu muốn biến có thể nhận giá trị null, bạn thêm kí tự ? vào sau kiểu_dữ_liệu_của_biến, chẳng hạn

void main() {
  var name = 'Phuong';
  print(name);//kết quả Phuong
  
  int? age = 30;
  print(age);//kết quả 30
  age = null;
  print(age);//kết quả null
}

Một ví dụ nữa

main() {
  int? a;
  print(a.runtimeType); //kết quả kiểu Null
  print(a); //kết quả null
  a = 5;
  print(a.runtimeType); //kết quả kiểu int
  a = null;
  print(a.runtimeType);////kết quả kiểu Null
}

Bạn có thể xem thêm về Null safety Dart / Null safety Flutter là gì?

Khi khai báo biến sử dụng từ khóa var thì khi sử dụng đến biến đó, trình biên dịch Dart sẽ tự xác định kiểu dữ liệu của biến cho chúng ta.

Ví dụ var x; để khai báo một biến có tên là x. Viết int x; để khai báo một biến kiểu số nguyên int và có tên là x.

Khai báo nhiều biến cùng lúc [thường các biến có cùng kiểu], chúng ta sử dụng cú pháp:

var tên_biến1, tên_biến2;

hoặc kiểu_dữ_liệu_của_biến tên_biến1, tên_biến2, tên_biến3;

1.2. Giá trị ban đầu của biến

Xét chương trình sau sử dụng hai biến kiểu số nguyên intab, thực hiện phép cộng hai số ab rồi in kết quả ra màn hình.

void main() {
  int a, b;
  print(a+b);
}

Tuy nhiên khi chạy chương trình, trình biên dịch báo lỗi như hình sau:

khai báo biến trong dart flutter

Nguyên nhân là chúng ta mới khai báo hai biến ab chứ chưa cung cấp cho chúng một giá trị nào cả. Do đó không thể thực hiện được phép cộng.

Chúng ta tiến hành cung cấp cho hai biến a,b các giá trị, chương trình chạy thành công, kết quả thu được là 9:

khai bao bien trong dart

Chúng ta có thể vừa khai báo biến, vừa cung cấp cho biến một giá trị mặc định khởi đầu như trong ví dụ sau:

void main() {
  int a = 5;
  int b = 4;
  print(a+b);
}

hoặc viết gọn hơn

void main() {
  int a = 5, b = 4;
  print(a+b);
}

1.3. Kiểu của biến

Nếu khai báo với từ khóa var, kiểu của biến sẽ được Dart tự động xác định. Nếu muốn chỉ định kiểu của biến, chúng ta đã biết cách khai báo ở trên. Tuy nhiên, đối với những biến nhận giá trị thuộc mọi kiểu, chúng ta có thể khai báo chúng là kiểu dynamic hoặc Object.

void main() {
  dynamic a = 4;
  dynamic b;
  print(a.runtimeType);
  a = 'Phuong';
  print(a.runtimeType);
  print(b.runtimeType);
}

Khi chạy chương trình sẽ được kết quả như hình sau:

bien va kieu du lieu trong dart

Nếu khai báo biến có kiểu dynamic thì giá trị mặc định của biến sẽ là null còn khai báo Object thì biến sẽ không có giá trị mặc định. Ví dụ sau, khai báo biến a có kiểu dynamic thì a sẽ nhận giá trị mặc định là null, còn biến b khai báo kiểu Object thì sẽ không có giá trị mặc định nào cả, kể cả giá trị null. Do đó hãy cẩn thận.

khai báo biến kiểu object

1.4. Sự khác nhau giữa từ khoá var và dynamic

Nếu bạn khai báo biến bằng từ khoá var và gán giá trị mặc định ngay thì biến sẽ có kiểu là kiểu của giá trị mặc định đó, nếu không thì biến sẽ có kiểu dynamic.

void main() {
  var a;
  print(a.runtimeType); //Null vì giá trị mặc định của dynamic là null
  a = 5; //OK
  print(a.runtimeType); //kiểu int
  a = 'Phuong'; //OK
  print(a.runtimeType);//kiểu String

  var b = 5;
  print(b.runtimeType);//Kiểu int
  b = 3; //OK  
  b = 'five'; //Erros
}

Dart cũng cung cấp một toán tử đặc biệt ??, gọi là Null-aware để đảm bảo null safe trong quá trình thực thi code.

Sử dụng toán tử ??=, để gán một giá trị cho biến nếu và chỉ nếu biến đó đang có giá trị null.

main() {
  var a; //biến kiểu dynamic a, mặc định nhận giá trị null
  a ??= 3; //Gán 3 cho a nếu a đang có giá trị null, phép gán thành công
  print(a); //Phép gán trên thành công nên a nhận giá trị 3
  a ??= 5; //Gán 5 cho a nếu a đang có giá trị null, phép gán không thành công
  print(a); //a vẫn có giá trị như lúc trước khi thực hiện phép gán
}

Một toán tử null-aware khác là ??, toán tử này trả về biểu thức nằm bên trái toán tử ?? nếu và chỉ nếu biểu thức đó có giá trị khác null, ngược lại thì trả về biểu thức nằm phía bên phải.

print(1 ?? 3); //In ra 1.
print(null ?? 12); // In ra 12.

1.4. Quy tắc đặt tên trong Dart

Trong cú pháp khai báo trên, tên_biến được đặt tên theo các quy tắc bắt buộc sau:

  • Tên phải bắt đầu bằng kí tự từ a đến z, hoặc từ A đến Z hoặc dấu gạch dưới _ và theo sau là chữ hoặc số.
  • Tên có phân biệt chữ HOA và chữ thường, do đó ten_bienTen_Bien là hai tên khác nhau.

Ngoài các quy tắc bắt buộc phải tuân theo đó, chúng ta nên đặt tên theo các quy ước ngầm sau:

  • Nên đặt tên có ý nghĩa, điều này giúp việc đọc hiểu code được dễ dàng hơn.
  • Đặt tên ngắn gọn, giúp việc gõ code được nhanh hơn, thường chúng ta sẽ viết tắt tên bằng cách viết HOA chữ cái đầu của từ viết tắt,  ví dụ IOStream  InputOutputStream...
  • Nên đặt tên kiểu UpperCamelCase cho lớp class, enums, tham số (chữ đầu của từ là chữ in ví dụ HttpRequest)
  • Tên file, thư viện viết chữ thường, các từ nối với nhau bởi _ ví dụ abc_xyz.dart
  • Biến, hằng, object đặt tên kiểu lowerCamelCase, chữ đầu các từ viết IN HOA, trừ từ đầu tiên ( ví dụ defaultTimeout)

1.3. Khai báo hằng số trong Dart

Để khai báo một hằng số trong Dart, chúng ta sử dụng cú pháp

const tên_hằng_số = giá_trị;

Ví dụ, sử dụng const pi = 3.1415926;để khai báo hằng số có tên pi và có giá trị bằng 3.1415926

2. Các kiểu dữ liệu trong Dart

Dart hỗ trợ các kiểu dữ liệu xây dựng sẵn (built-in types) sau:

  • Kiểu số num gồm có hai kiểu con là kiểu số nguyên int, số thực double
  • Kiểu xâu (kiểu chuỗi) String
  • Kiểu logic bool
  • Kiểunull
  • Kiểu danh sách List tương tự như kiểu mảng arrays trong các ngôn ngữ khác
  • Kiểu tập hợp set
  • Kiểu map tương tự kiểu từ điển dict như trong Python
  • Kiểu ngày tháng DateTime
  • Kiểu dynamic là kiểu chấp nhận mọi kiểu dữ liệu khác, bạn có thể gán một giá trị là số, xâu, ngày tháng… cho biến kiểu dynamic

Ngoài ra còn có một số kiểu khác nữa như Uri hoặc Error. Chúng ta sẽ lần lượt tìm hiểu về các kiểu dữ liệu trong Dart này trong các bài tiếp theo của loạt bài Tự học lập trình Dart này.

2.1. Kiểu số num trong Dart

Kiểu số num trong Dart bao gồm có kiểu số nguyên int và kiểu số thực double, bài chi tiết xin mời các bạn xem tại đây Kiểu số trong Dart/Flutter

2.2. Kiểu logic bool trong Dart

2.3. Kiểu xâu String trong Dart

3. Phân biệt constfinal trong Dart

  • Để khai báo một hằng số trong Dart, chúng ta sử dụng từ khóa const.
  • Để khai báo một biến chỉ nhận giá trị một lần và không thay đổi trong suốt chương trình, chúng ta sử dụng từ khóa final. Đương nhiên vẫn có thể sử dụng từ khóa var hoặc khai báo định kiểu cho biến đó, nhưng cách này không tối ưu bằng cách sử dụng final.

Một biến không thay đổi trong suốt chương trình thì có gì khác hằng số, và đâu là sự khác nhau của hai cách khai báo này? Bạn sẽ hiểu rõ hơn điều này khi chúng ta thảo luận về lớp class ở những bài sau.

Có thể coi finalconst đều biểu diễn cho các hằng số, nhưng const là hằng số trong lúc biên dịch (compile-time) còn const là hằng số và sẽ nhận được trong lúc chạy chương trình run-time.

hocbaicungcon

3 Comments

  1. ở chỗ code vd ??=, các bạn nói int có giá trị mặc định là null, và có thể gán bằng ??= lần đầu, còn lần sau thì không được.
    Bạn có chắc default value của int là null?? Và ví dụ của bạn là chính xác không ạ??

    • Ví dụ đó chính xác ở thời điểm viết bài bạn nhé. Ở thời điểm bây giờ Dart đã hỗ trợ null safety nên sẽ báo lỗi. Bạn xem bài nói về null sàety để rõ hơn nhé.

    • Mình vừa cập nhật lại bài viết theo null safety, bạn xem lại nhé.

Leave a Reply

Your email address will not be published. Required fields are marked *