枚举
枚举(Enum)是一种用于表示固定数量的常量值的特殊类(class),在第1章数据类型一节中已经简单介绍过,文本将更详细地讨论它。
简单枚举
使用关键字enum
声明一个简单枚举如下:
// ex14d.dart
enum Color { red, green, blue }
void main() {
print(Color.red); // Output: Color.red
print(Color.blue.name); // Output: blue
print(Color.blue.index); // Output: 2
}
每个枚举值都有个与之关联的数字,称之为index,该数字从0开始。此例中 red
, green
, blue
的 index
分别为0、1、2,可见index
是按枚举值的声明顺序依次分配的。
详尽性检查
当枚举值用在switch语句或表达式时,Dart编译器将进行详尽性检查(完备性检查),迫使程序员处理所有的枚举值。
// ex471.dart
enum Color { red, green, blue }
String example(Color color) => switch (color) {
Color.red => 'Red apple',
Color.green => 'Green tree',
Color.blue => 'Blue sky',
};
void main() {
print(example(Color.blue)); // Output: Blue sky
}
下面这段代码无法通过编译,因为 Color.blue
没有得到处理。
// ex472.dart
enum Color { red, green, blue }
String example(Color color) => switch (color) {
Color.red => 'Red apple',
Color.green => 'Green tree',
};
可使用 wildcard (即通配符 _
)匹配剩余的枚举值。
// ex473.dart
enum Color { red, green, blue, orange, pink }
String example(Color color) => switch (color) {
Color.red => 'Red apple',
Color.green => 'Green tree',
_ => 'Whatever',
};
void main() {
print(example(Color.blue)); // Output: Whatever
}
增强型枚举
枚举是一种特殊的类,它可以有自己的字段、方法和常量构造器,这便是增强型枚举的概念(自Dart 2.17开始引入)。
// ex474.dart
enum Status {
// 1
continue_(100, message: 'Continue'),
ok(200, message: 'OK'),
movedPermanently(301, message: 'Moved Permanently'),
notFound(404, message: 'Not Found'),
badGateway(502, message: 'Bad Gateway');
final int code; // 2
final String message; // 2a
const Status(this.code, {required this.message}); // 3
static Status of(int code) => // 4
values.firstWhere((status) => status.code == code);
bool get is2xx => (code ~/ 100) == 2; // 5
bool get isOk => this == ok; // 5a
@override
String toString() => '$message($code)'; // 6
}
void main() {
print(Status.values); // 7
// Output: [Continue(100), OK(200), Moved Permanently(301), Not Found(404), Bad Gateway(502)]
print(Status.ok); // Output: OK(200)
print(Status.of(404)); // Output: Not Found(404)
print(Status.ok.isOk); // Output: true
print(Status.of(502).is2xx); // Output: false
Status.of(10);
// Unhandled exception:
// Bad state: No element
}
Status
是一个枚举,首先列出它所有可能的取值continue_
、ok
等,这些枚举值是常量对象,通过调用常量构造器得到,例如ok(200, message: 'OK')
;code
和message
是Status
的实例变量,它们都必须声明为final
;Status
的常量构造器,code
是位置参数,message
是命名参数;of
是一个静态方法,将参数code
转换为枚举值,此方法可以改为factory构造器;
factory Status.of(int code) => // 4
values.firstWhere((status) => status.code == code);
is2xx
和isOk
是两个自定义的getter;- 重写
toString()
方法; Status.values
是由Dart运行时(runtime)自动创建的getter,返回包含Status
所有枚举值的一个列表(List<Status>
), 其元素的顺序与它们被声明的顺序一致。
增强型枚举与普通类有着类似的语法,但有如下限制:
- 实例变量必须是
final
的,包括通过 mixin 添加的变量; - 所有的生成构造函数必须是常量构造器,即用
const
进行修饰; - 不能继承其它类,因为它自动继承了
Enum
类; - 不能重写
index
、hashCode
和 运算符==
; - 不能声明名为
values
的成员,因为它会与自动生成的values
getter 冲突; - 枚举的所有实例都必须在开头声明,并且至少得声明一个实例。
这些限制听起来都比较合理,也不难理解,不再赘述。