openplanning

Hướng dẫn và ví dụ Dart Closures

  1. Closure là gì?
  2. Cú pháp mũi tên
  3. Lớp Function
  4. Closure trong tham số

1. Closure là gì?

Trong ngôn ngữ lập trình Dart, Closure (bao đóng) là một hàm đặc biệt.
  • Giống như hàm, Closure là một khối lệnh với các tham số và có thể trả về một giá trị hoặc không trả về gì cả.
  • Khác với hàm, Closure không có tên, tuy nhiên bạn có thể định danh cho Closure thông qua một biến.
Cú pháp:
// Closure syntax
(data_type1 arg1, data_type2 arg2, data_typeN argN) {
   // Statements
}
// Declare a variable as an alias for Closure
var alias = (data_type1 arg1, data_type2 arg2, data_typeN argN) {
   // Statements
};
Ví dụ: Chúng ta khai báo một Closure có 1 tham số, và gọi nó một cách trực tiếp.
closure_ex1.dart
void main() {  
  // Create a Closure!
  (String name) {
    print('Hello $name!');
  };
  // Create a Closure and call it directly!
  (String name)  {
    print('Bye $name!');
  }('Tom');
}
Output:
Bye Tom!
Ví dụ: Khai báo một biến như một cách để định danh cho Closure:
closure_ex2.dart
void main() {  
  // Declare a variable as an alias for Closure
  var sum = (int a, int b) {
    return a + b;
  };
  // Call a closure.
  var result = sum(100, 200); // 300
  print('result = $result');
}

2. Cú pháp mũi tên

Nếu nội dung của Closure chỉ bao gồm duy nhất một biểu thức, bạn có thể viết nó một cách ngắn gọn hơn với cú pháp mũi tên (Arrow syntax):
var alias1 =  (data_type1 arg1, data_type2 arg2, data_typeN argN) {
     print('Something');
}
// Same as:
var alias1 =  (data_type1 arg1, data_type2 arg2, data_typeN argN) => print('Something');

var alias2 =  (data_type1 arg1, data_type2 arg2, data_typeN argN) {
     return a_value;
}
// Same as:
var alias2 =  (data_type1 arg1, data_type2 arg2, data_typeN argN)  => a_value;
Ví dụ:
closure_arrow_ex1.dart
void main() {
  // Create a Closure
  var sum = (int a, int b) => a + b;

  var result = sum(100, 200); // Call a closure.
  print('result = $result');

  // Create a Closure
  var sayHello = (String name) => print('Hello $name');
  sayHello('Tom'); // Call a closure.
}
Output:
result = 300
Hello Tom

3. Lớp Function

Trong ngôn ngữ Dart, Closure là một đối tượng của lớp Function, vì vậy bạn có thể khai báo một Closure với cú pháp dưới đây:
Cú pháp:
Function(type1 arg1, type2 arg2, typeN argN) func = (type1 arg1, type2 arg2, typeN argN) {
   // Statements
};
// Or:
return_type Function(type1 arg1, type2 arg2, typeN argN) func;

func = (type1 arg1, type2 arg2, typeN argN) {
   // Statements
};
Ví dụ:
closure_func_ex1.dart
void main() {
  // Function Type: (int, int) --> (int)
  Function(int a, int b) sum = (int a, int b) {
    return a + b;
  };
  // Function Type: (int, int) --> (int)
  int Function(int a, int b) minus;
  minus = (int a, int b) => a - b;

  var result1 = sum(100, 200); // 300
  print('result1 = $result1');

  var result2 = minus(100, 200); // -100
  print('result2 = $result2');
}

4. Closure trong tham số

Closure có thể xuất hiện như là một tham số của một hàm, closure, phương thức hoặc constructor khác.
// A Function to calculate Tax.
// It accepts 2 arguments:
//  1 - int amount
//  2 - Closure
void printTaxAmount(int amount, double Function(int amount) taxFormula) {
  var tax = taxFormula(amount);
  print('tax = $tax');
}

// Same as:
void printTaxAmount(int amount, double taxFormula(int amount)) {
  var tax = taxFormula(amount);
  print('tax = $tax');
}
Ví dụ:
closure_in_args_ex1.dart
// A Function to calculate Tax.
// It accepts 2 arguments:
//  1 - int amount
//  2 - Closure
void printTaxAmount(int amount, double Function(int amount) taxFormula) {
  var tax = taxFormula(amount);
  print('tax = $tax');
}
void main() {
  // Create a Closure (Tax calucation formula of US)
  var usTaxFormula = (int amount) {
    return 10 * amount / 100; // return a double type.
  };
  // Create a Closure (Tax calucation formula of Vietnam)
  var vnTaxFormula = (int amount) {
    return 5 * amount / 100; // return a double type.
  };
  const amount = 1000;
  printTaxAmount(amount, usTaxFormula); // 100.0
  printTaxAmount(amount, vnTaxFormula); // 50.0
}
Output:
tax = 100.0
tax = 50.0
List.generate Example:
Constructor List.generate của lớp List có một tham số là một Closure, chúng ta hãy xem một ví dụ về cách sử dụng constructor này.
List.generate Constructor
external factory List.generate(int length, E generator(int index), {bool growable = true});
Ví dụ:
closure_in_args_ex3.dart
// List.generate Constructor:
// external factory List.generate(int length, E generator(int index), {bool growable = true});
void main() {
  // (int index) --> (String)
  var generator = (int index) {
    return 'Value ' + index.toString();
  };
  // Create a List with 5 elements:
  List<String> myList = List.generate(5, generator, growable: true);
  print(myList); // [Value 0, Value 1, Value 2, Value 3, Value 4]
}
Output:
[Value 0, Value 1, Value 2, Value 3, Value 4]