Dart Enums and Symbols
An enum is used to define a set of named constant values, making code more readable.
This chapter introduces how to define Dart enums, enhanced enums (with methods and properties), as well as the Symbol and Rune types.
enum Enum Definition
An enum is a special kind of class used to represent a fixed number of constant values.
The most typical scenarios are representing finite options such as states, directions, colors, etc.
Example
enum Status {
pending, // Pending
approved, // Approved
rejected, // Rejected
cancelled, // Cancelled
}
void main() {
// Using enum values
Status currentStatus = Status.pending;
print('Current status: $currentStatus');
// Get the index via .index (starting from 0)
print('Index value: ${currentStatus.index}'); // 0
// Get all enum values via .values
print(All statuses: ${Status.values});
// Iterate through all enum values
for (var status in Status.values) {
print(EXAMPLE status: $status, index: ${status.index});
}
// Get enum value by string
Status parsed = Status.values.byName('approved');
print(Parsed status: $parsed);
// Using enums in switch
switch (currentStatus) {
case Status.pending:
print(Order pending);
break;
case Status.approved:
print(Order approved);
break;
case Status.rejected:
print(Order rejected);
break;
case Status.cancelled:
print(Order cancelled);
break;
}
}
当前状态: Status.pending 索引值: 0 所有状态: [Status.pending, Status.approved, Status.rejected, Status.cancelled] EXAMPLE 状态: Status.pending, 索引: 0 EXAMPLE 状态: Status.approved, 索引: 1 EXAMPLE 状态: Status.rejected, 索引: 2 EXAMPLE 状态: Status.cancelled, 索引: 3 解析出的状态: Status.approved 订单待处理
Enums and switch are a perfect match. When you handle all enum values in a switch, the Dart compiler checks whether you have covered all cases. This avoids bugs caused by missing branches.
Enhanced Enums (with Methods and Properties)
Dart 3.0 introduced Enhanced Enums, allowing enums to have fields, methods, and constructors.
Example
enum HttpStatus {
// Enum values pass parameters via the constructor
ok(200, Request successful),
created(201, Resource created),
badRequest(400, Bad request),
unauthorized(401, Unauthorized),
notFound(404, Resource not found),
serverError(500, Internal server error);
// Member variables: each enum value has code and message
final int code;
final String message;
// Constructor: must be const
const HttpStatus(this.code, this.message);
// Enum method
bool get isSuccess => code >= 200 && code < 300;
bool get isClientError => code >= 400 && code < 500;
bool get isServerError => code >= 500;
// Static method: find enum by status code
static HttpStatus? fromCode(int code) {
try {
return HttpStatus.values.firstWhere((s) => s.code == code);
} catch (_) {
return null;
}
}
}
void main() {
var status = HttpStatus.notFound;
print(EXAMPLE HTTP status: $status);
print(Status code: ${status.code});
print(Message: ${status.message});
print(Is successful: ${status.isSuccess});
print('Is client error: ${status.isClientError}');
// Look up using a static method
var found = HttpStatus.fromCode(201);
if (found != null) {
print('Found status: ${found.message}');
}
var unknown = HttpStatus.fromCode(999);
print('Unknown status code: $unknown');
}
EXAMPLE HTTP 状态: HttpStatus.notFound 状态码: 404 Message: 资源未找到 是否成功: false 是否客户端错误: true 找到状态: 资源已创建 未知状态码: null
Enhanced enums elevate enums from "named constant collections" to "types with behavior," allowing them to encapsulate logic related to the enum.
The constructors of enhanced enums must be const, and member variables must be final. This is because enum values themselves are compile-time constants.
Symbol type
Symbol represents identifiers in Dart programs (variable names, function names, etc.).
It is not commonly used in daily development; it is mainly used in reflection and code generation scenarios.
Example
// Use # prefix to create Symbol
Symbol sym1 = #example;
Symbol sym2 = #helloWorld;
print('Symbol 1: $sym1'); // Symbol("example")
print('Symbol 2: $sym2'); // Symbol("helloWorld")
// Symbol comparison
Symbol sym3 = #example;
print('sym1 == sym3: ${sym1 == sym3}'); // true
// Symbol can be used as a Map key
var metadata = {
#author: 'EXAMPLE',
#version: '1.0.0',
#description: Dart Tutorial,
};
print('Author: ${metadata[#author]}');
}
Symbol 1: Symbol("example")
Symbol 2: Symbol("helloWorld")
sym1 == sym3: true
作者: EXAMPLE
Symbols are typically minified after Dart compilation, so do not rely on the result of Symbol("example").toString() for logical decisions. The correct use of Symbol is for reflection operations through the dart:mirrors library.
Runes and Unicode
Rune is the type in Dart that represents Unicode code points.
In Dart, strings are sequences encoded in UTF-16.
For characters outside the Basic Multilingual Plane (BMP), such as emoji, Rune is needed to handle them.
Example
// Get the Unicode code points of the string
String text = 'EXAMPLE';
print('Character: $text');
print('Code point list: ${text.runes.toList()}');
// Iterate over each character and its code point
for (var char in text.runes) {
print('${String.fromCharCode(char)} -> U+${char.toRadixString(16).toUpperCase().padLeft(4, '0')}');
}
// Create a character from a code point
var heart = String.fromCharCode(0x2764);
print('Heart: $heart');
// Handle multi-code-point characters (such as some emoji)
var smile = '\u{1F600}'; // Use \u{} syntax to represent characters beyond the BMP
print('Smiley: $smile');
// Get the code points of a multi-code-point character
print('Smiley code points: ${smile.runes.map((r) => 'U+${r.toRadixString(16).toUpperCase()}').toList()}');
}
字符: EXAMPLE 码点列表: [82, 85, 78, 79, 79, 66] R -> U+0052 U -> U+0055 N -> U+004E O -> U+004F O -> U+004F B -> U+0042 心形: ❤ 笑脸: 😀 笑脸码点: [U+1F600]
In most daily development, you don't need to work with Rune directly; strings themselves handle Unicode well.
Rune is mainly used when precise manipulation of character code points is required, such as in low-level scenarios like text editors and font rendering.
other extensions