Dot shorthands(点号简写)
点号简写允许在上下文已经明确类型时,省略枚举名或类名,把 Type.member 写成 .member。它能减少重复,但不会进行动态查找:编译器必须从表达式所在位置得到足够精确的上下文类型。
版本说明:点号简写从 Dart 3.10 开始可用。使用该语法的 package 需要设置兼容的最低 SDK 约束。
枚举值简写
变量声明已经给出枚举类型时,可以省略枚举名:
enum Status { idle, running, stopped }
void main() {
Status current = .running;
print(current == Status.running); // true
}
这里左侧要求 Status,因此编译器把 .running 解析为 Status.running。
点号简写也适用于参数和返回值等具有明确期望类型的位置:
enum Alignment { start, center, end }
void setAlignment(Alignment alignment) {
print(alignment);
}
Alignment defaultAlignment() => .center;
void main() {
setAlignment(.end);
}
调用构造函数
.new() 表示调用上下文类型的无名构造函数,.named() 表示调用命名构造函数:
class Point {
final int x;
final int y;
const Point(this.x, this.y);
const Point.origin() : this(0, 0);
}
void main() {
Point first = .new(2, 3);
Point second = .origin();
print('${first.x}, ${second.y}'); // 2, 0
}
在常量位置,可以把 const 与简写组合:
const Point origin = .origin();
静态成员简写
只要静态成员的结果与上下文类型兼容,也可以省略类型名:
class ThemeMode {
final String name;
const ThemeMode._(this.name);
static const light = ThemeMode._('light');
static const dark = ThemeMode._('dark');
}
void main() {
ThemeMode mode = .dark;
print(mode.name); // dark
}
简写从一个静态成员、构造函数或枚举值开始,之后还可以继续进行成员访问或方法调用。
switch 与集合中的简写
分支结果具有统一上下文类型时,点号简写可以让重复的类型名更少:
enum Result { success, failure }
Result parse(bool valid) => switch (valid) {
true => .success,
false => .failure,
};
void main() {
List<Result> results = [.success, .failure];
print(results);
}
List<Result> 为集合元素提供了 Result 上下文,函数返回类型则为每个 switch 分支提供上下文。
相等比较的特殊规则
在 == 或 != 的右侧直接使用点号简写时,左侧表达式的静态类型可作为上下文:
enum Color { red, green, blue }
void main() {
Color color = Color.green;
if (color == .green) {
print('matched');
}
}
这个规则具有方向性,.green == color 不成立,因为简写位于左侧时没有可用的左侧类型。复杂表达式或先把左侧转为 Object,也可能使类型上下文丢失。
什么时候不能使用
var 本身需要从右侧推断类型,因此下面的写法缺少上下文:
enum Status { idle, running }
void main() {
// var status = .running; // 编译错误:无法确定 .running 属于哪个类型
var status = Status.running; // 正确
}
当多个类型都可能满足上下文、期望类型过宽,或成员不属于推断出的类型时,也必须写出完整类型名。公共 API 或较长表达式中,如果简写降低可读性,保留完整名称更合适。
TypeScript 对比:TypeScript 通常需要写出
Status.running,没有与 Dart.running相同的上下文点号简写。对象字面量的上下文类型推断与此有相似之处,但不能用来省略枚举或类名。
常见误区
.member依赖静态上下文类型,不是运行时按名称搜索成员。var value = .member通常无法推断,因为左右两侧都没有提供类型。- 相等比较只允许右侧简写借用左侧类型,交换两边可能导致编译错误。
- 简写不意味着成员变成实例成员;它仍然解析为某个类型的静态成员或构造函数。
小结
- 点号简写在类型已知时把
Type.member缩短为.member。 - 它适用于枚举值、静态成员、无名构造函数
.new()和命名构造函数。 - 参数、返回值、集合元素和
switch分支都可能提供上下文类型。 ==、!=右侧具有从左侧取得类型的特殊规则。- 上下文不明确或可读性下降时,应使用完整类型名。