點燈坊

失くすものさえない今が強くなるチャンスよ

使用 final 與 const 定義常數

Sam Xiao's Avatar 2024-08-21

Dart 提供了 finalconst 定義 常數,兩者大致上意義相同,但仍有些微差異。

Version

Dart 3.3

Constant Value

void main() {
  const pi1 = 3.14159;
  final pi2 = 3.14159;

  print('PI1: $pi1');
  print('PI2: $pi2');
}
  • 對於 value 型別 (int, double, String, bool):constfinal 行為是相同的

Constant Object

List

void main() {
  final arr = [1, 2, 3];
  // arr = [4, 5, 6]; // X
  // arr[2] = 0;      // O

  print('arr: $arr');
}
  • final 用於 List 時,變數不能再指定其他 List,但 List 內的值可修改
void main() {
  const arr = [1, 2, 3];
  // arr = [4, 5, 6]; // X
  // arr[2] = 0;      // X

  print('arr: $arr');
}
  • const 用於 List 時,變數不能再指定其他 List,且 List 內的值也不可修改,是真 immutable

Map

void main() {
  final student = {'name': 'Sam', 'ID': 001};
  // student = {'name': 'John', 'ID': 002}; // X
  // student['name'] = 'John';  // O

  print('name: $student');
}
  • final 用於 Map 時,變數不能再指定其他 Map,但 Map 內的值可修改
void main() {
  const student = {'name': 'Sam', 'ID': 001};
  // student = {'name': 'John', 'ID': 002};
  // student['name'] = 'John';

  print('name: $student');
}
  • const 用於 Map 時,變數不能再指定其他 Map,且 Map 內的值也不可修改,真 immutable

Lazy Initialization vs. Compile-time

final

void main() {
  final now = DateTime.now(); // O

  print('now: $now');
}
  • final 為 Lazy Initialization constant,若常數的值來自於 run time,則只能使用 final

const

void main() {
  const now = DateTime.now(); // X

  print('now: $now');
}
  • const 為 compile-time constant,若常數的值來自於 run-time,則使用 final 會報錯,因為 compile-time 時還沒有運行 Datetime.now()

Conclusion

  • finalconst 都支援 Type Inference,可 不用 宣告型別
  • 若用於 value,則 finalconst 行為相同
  • 若用於 object,則 finalconst 行為不盡相同
  • final 影響的是 變數本身,const 影響的是
  • Dart 的 final 類似於 JavaScript 的 const 並非 Immutable,對於 Object 類的 List (Array) 或 Map (Object) 無效;而 Dart 的 const 為真 Immutable,對於 Object 類的 List (Array) 或 Map (Object) 依然 有效
  • Dart 的 const 對 Immutable 完美支援,解決 JavaScript 的 const 半吊子問題

Reference

Dart, Final and const