以下是 Dart 文档中使用的术语定义。
常量上下文
#常量上下文是指代码区域,其中不需要包含 const
关键字,因为该区域中的所有内容都必须是常量,因此隐含了该关键字。以下位置是常量上下文
在以
const
关键字为前缀的列表、映射或集合字面量中的所有内容。示例dartvar l = const [/*constant context*/];
常量构造函数调用中的参数。示例
dartvar p = const Point(/*constant context*/);
以
const
关键字为前缀的变量的初始化程序。示例dartconst v = /*constant context*/;
注释
case
子句中的表达式。示例dartvoid f(int e) { switch (e) { case /*constant context*/: break; } }
明确赋值
#确定性赋值分析是指确定代码中每个局部变量在每个位置的以下情况:
- 该变量肯定已被赋值(确定性赋值)。
- 该变量肯定未被赋值(确定性未赋值)。
- 该变量可能已被赋值,也可能未被赋值,具体取决于到达该位置的执行路径。
确定性赋值分析有助于查找代码中的问题,例如可能未被赋值的变量被引用,或者只能赋值一次的变量在可能已被赋值后再次被赋值。
例如,在以下代码中,变量 s
在作为参数传递给 print
时,肯定未被赋值
void f() {
String s;
print(s);
}
但在以下代码中,变量 s
肯定已被赋值
void f(String name) {
String s = 'Hello $name!';
print(s);
}
确定赋值分析甚至可以判断在存在多个可能的执行路径的情况下,变量是否被确定赋值(或未赋值)。在以下代码中,如果执行通过 `if` 语句的真或假分支,则会调用 `print` 函数,但由于无论哪个分支被执行,`s` 都会被赋值,因此在传递给 `print` 之前,它被确定赋值。
void f(String name, bool casual) {
String s;
if (casual) {
s = 'Hi $name!';
} else {
s = 'Hello $name!';
}
print(s);
}
在流程分析中,`if` 语句的末尾被称为连接点——两个或多个执行路径合并在一起的地方。在存在连接点的情况下,分析表明,如果变量在所有合并的路径上都被确定赋值,则该变量被确定赋值;如果变量在所有路径上都被确定未赋值,则该变量被确定未赋值。
有时,变量在一个路径上被赋值,而在另一个路径上没有被赋值,在这种情况下,变量可能已经被赋值,也可能没有被赋值。在以下示例中,`if` 语句的真分支可能被执行,也可能不被执行,因此变量可能被赋值,也可能没有被赋值。
void f(String name, bool casual) {
String s;
if (casual) {
s = 'Hi $name!';
}
print(s);
}
如果存在一个不为 `s` 赋值的假分支,情况也是如此。
循环的分析稍微复杂一些,但遵循相同的基本推理。例如,`while` 循环中的条件总是被执行,但循环体可能被执行,也可能不被执行。因此,就像 `if` 语句一样,在 `while` 语句的末尾,在条件为 `true` 的路径和条件为 `false` 的路径之间存在一个连接点。
有关更多详细信息,请参阅 确定赋值规范。
函数
#除非另有说明,否则术语函数指的是顶层函数、局部函数、静态方法和实例方法。
有关更多详细信息,请参阅 函数 文档。
不可反驳模式
#不可反驳模式是指始终匹配的模式。不可反驳模式是唯一可以出现在不可反驳上下文中的模式:声明 和 赋值 模式上下文。
Mixin 应用
#mixin 应用是在将 mixin 应用于类时创建的类。例如,考虑以下声明
class A {}
mixin M {}
class B extends A with M {}
类 `B` 是将 `M` 应用于 `A` 的 mixin 应用的子类,有时被称为 `A+M`。类 `A+M` 是 `A` 的子类,并且具有从 `M` 复制的成员。
可以通过将其定义为来为混合应用程序指定实际名称。
class A {}
mixin M {}
class A_M = A with M;
给定此 A_M
的声明,以下 B
的声明等同于原始示例中 B
的声明。
class B extends A_M {}
覆盖推断
#覆盖推断是指根据被覆盖方法或方法中的对应类型推断方法声明中任何缺失类型的过程。
如果候选方法(缺少类型信息的 method)覆盖单个继承方法,则将推断被覆盖方法中的对应类型。例如,考虑以下代码
class A {
int m(String s) => 0;
}
class B extends A {
@override
m(s) => 1;
}
B
中 m
的声明是一个候选方法,因为它缺少返回类型和参数类型。因为它覆盖了单个方法(A
中的 m
方法),所以将使用被覆盖方法中的类型来推断缺失的类型,并且它将如同 B
中的方法被声明为 int m(String s) => 1;
一样。
如果候选方法覆盖多个方法,并且其中一个被覆盖方法 Ms 的函数类型是所有其他被覆盖方法的函数类型的超类型,则使用 Ms 来推断缺失的类型。例如,考虑以下代码
class A {
int m(num n) => 0;
}
class B {
num m(int i) => 0;
}
class C implements A, B {
@override
m(n) => 1;
}
C
中 m
的声明是覆盖推断的候选方法,因为它缺少返回类型和参数类型。它覆盖了 A
中的 m
和 B
中的 m
,因此我们需要从其中选择一个来推断缺失的类型。但由于 A
中 m
的函数类型(int Function(num)
)是 B
中 m
的函数类型(num Function(int)
)的超类型,因此使用 A
中的函数来推断缺失的类型。结果与在 C
中将方法声明为 int m(num n) => 1;
相同。
如果所有被覆盖方法中没有一个方法的函数类型是所有其他被覆盖方法的函数类型的超类型,则会发生错误。
部分文件
#部分文件是包含 part of
指令的 Dart 源文件。有关使用指南,请访问 Effective Dart 条目。
可能非空
#如果类型是显式非空类型或类型参数,则该类型为潜在非空类型。
如果类型名称后面没有问号,则该类型为显式非空类型。请注意,有一些类型始终为空,例如 Null
和 dynamic
,并且 FutureOr
只有在后面没有问号并且类型参数为非空类型(例如 FutureOr<String>
)时才为非空类型。
类型参数是潜在非空类型,因为实际运行时类型(作为类型参数指定的类型)可能是非空类型。例如,给定 class C<T> {}
的声明,类型 C
可以与非空类型参数一起使用,如 C<int>
中所示。
公共库
#公共库是指位于包的lib
目录中,但不在lib/src
目录中的库。
可反驳模式
#可证伪模式是指可以用来测试一个值以确定模式是否与该值匹配的模式。如果匹配失败,则模式会证伪或拒绝匹配。可证伪模式出现在匹配上下文中。