哈Ha!我提请您注意Filip Hracek的文章“宣布声音为零的安全性”的译文,并附上我的评论:对于Dart团队来说,迈出了重要的一步,他们介绍了无效安全技术发展的技术预览。空安全避免了通常很难检测到的一整类错误,此外,它还提供了许多性能改进。目前,我们已经发布了初步的技术预览,正在等待您的反馈。
零安全性-使用空链接的安全工作。进一步在本文中,为简洁起见,并且由于术语的稳定性,将使用英文名称null,安全性null。而“零安全”的翻译则导致了完全相反的想法。
声音-在这种情况下(声音为零)可以翻译为“可靠”。
如果您有改进翻译的建议或发现错误-请以个人身份写,我们将尝试对其进行修复。
在本文中,我们将揭示Dart团队部署零安全的计划,并解释术语“声音零安全”背后的含义,以及这种方法与其他编程语言的区别。
所述版本于2020年6月10日发布。
为什么要取消安全性?
Dart是一种类型安全的语言。这意味着当您获得某种类型的变量时,编译器可以保证它属于该变量。但是,仅类型安全性不能保证变量不为null。
空错误是常见的。在GitHub上进行搜索可找到Dart代码中由空值引起的数千个报告(问题),甚至还有更多的提交试图解决这些问题。
在下面的示例中尝试发现零链接问题:
void printLengths(List<File> files) {
for (var file in files) {
print(file.lengthSync());
}
}
如果使用零参数调用此函数肯定会失败,但是还有第二种情况需要考虑:
void main() {
// Error case 1: passing a null to files.
printLengths(null);
// Error case 2: passing list of files, containing a null item.
printLengths([File('filename1'), File('filename2'), null]);
}
空安全解决了这个问题:
使用空安全,您可以更加自信地依赖代码。在运行时访问无效变量将不再有烦人的错误。编译时只有静态错误。
老实说,当前的实现仍然留有一些机会在执行时捕获空错误,以后还会更多。
声音(可靠)无效
Dart实施null安全性是合理的。如果我们使用上面的示例进行分析,则意味着Dart编译器100%确保文件数组及其中的元素不能为null。当Dart编译器分析您的代码并确定该变量不为null时,该变量将始终具有一个值:如果在调试器中检查可执行代码,您将发现在运行时根本不会归零。有些实现不是“可靠的”,在这种实现中,您仍然需要在运行时执行值的存在性检查。与其他语言不同,Dart与Swift共享实现可靠性。
, , , null safety . Swift, Kotlin Dart. .在Dart中强大的null安全实现会带来另一个不错的结果:这意味着您的程序可以更小,更快。由于Dart确实确保变量永远不会为空,因此Dart可以优化编译结果。例如,AOT编译器可以生成更小,更快的本机代码,因为它不需要为空引用添加检查。
我们已经看到了一些非常有希望的初步结果。例如,我们在模仿基准Flutter框架中典型渲染模式的微基准测试中看到了19%的性能提升。
基本原则
在继续进行零安全性的详细设计之前,Dart团队定义了三个基本原则:
默认情况下不可为空。 / **在文档中通常可以将其视为NNBD的缩写** /如果您未明确告知Dart变量可以为空,则它将视为不可为空。我们选择此值作为默认值,因为我们发现在API中,非零值是最常见的值。/ **这可能是当前Flutter API的翻版** /。
分阶段适用... 我们了解,应该有逐步逐步过渡到无效安全的可能性。实际上,您需要在同一项目中具有可空值和空安全代码。为此,我们计划提供工具来帮助代码迁移。
完全的可靠性(声音)。如上所述,Dart中的null安全是安全的。将整个项目和依赖项转换为零安全性后,您将获得所有的可靠性优势。
声明变量的安全性为空
基本语法很简单。以下是声明各种变量的示例。请注意,默认情况下使用非空变量,因此它们看起来相同,但它们的值不能为空。
// In null-safe Dart, none of these can ever be null.
var i = 42;
final b = Foo();
String m = '';
Dart将确保您绝不会为上述任何变量分配null。如果您甚至在一千行后尝试执行i = null,您将收到一个静态分析错误和红色的蠕动行-您的程序将拒绝编译。
如果希望变量为可空值,则可以使用“?” 像这样:
// These are all nullable variables.
int? j = 1; // Can be null later.
final Foo? c = getFoo(); // Maybe the function returns null.
String? n; // Is null at first. Can be null at any later time, too
上面列出的变量的行为与Dart当前版本中的所有变量完全相同。
'?''也可以在其他地方使用:
// In function parameters.
void boogie(int? count) {
// It's possible that count is null.
}
// In function return values.
Foo? getFoo() {
// Can return null instead of Foo.
}
// Also: generics, typedefs, type checks, etc.
// And any combination of the above.
但是,我再次希望您几乎永远不必使用“?”。您的绝大多数变量都是不可为空的。
使使用零安全更加容易
Dart小组正在努力使零安全性尽可能易于使用。例如,看下面的代码,它使用if测试null:
void honk(int? loudness) {
if (loudness == null) {
// No loudness specified, notify the developer
// with maximum loudness.
_playSound('error.wav', volume: 11);
return;
}
// Loudness is non-null, let's just clamp it to acceptable levels.
_playSound('honk.wav', volume: loudness.clamp(0, 11));
}
请注意,Dart非常聪明,可以意识到在传递if语句时响度不能为空。因此,Dart允许我们调用clip()方法,而不必用铃鼓跳舞。这种便利性是通过所谓的流分析来提供的:Dart解析器会像运行代码一样查看您的代码,从而自动找出有关代码的更多信息。
Flow analysis, Dart, , , . null safety, :
foo(dynamic str) {
if (str is String) {
// dynamic length,
// String
print(str.length);
}
}
, Dart , null, :
int sign(int x) {
// The result is non-nullable.
int result;
if (x >= 0) {
result = 1;
} else {
result = -1;
}
// By this point, Dart knows the result cannot be null.
return result;
}
- (, result = -1;), Dart , result — , .流分析仅在函数内部起作用。如果您具有全局变量或类字段,则Dart无法保证将为其分配值。Dart无法为整个应用程序的执行流程建模。因此,如果您知道该变量将在首次调用时被初始化,但是不能在声明它时对其进行初始化,则可以使用new late关键字。
class Goo {
late Viscosity v;
Goo(Material m) {
v = m.computeViscosity();
}
}
请注意,尽管最初无关紧要,但无法将v归零。Dart认为您不会尝试读取v,直到为其分配了非零值并且您的代码编译没有错误为止。
— .
, . , . Dart , , , , , Kotlin .
— Swift- , , force unwrap Dart.
void main() {
String? t;
print(t!.length);
}
( late ‘!’) .
late , - Dart. ‘required’ . ‘@required’, .
class Temp {
String str;
Temp({required this.str});
//
Temp.alt({strAtr}) : this.str = strAtr;
}
Dart团队已经进行了一年多的工作,以将零安全性带入技术预览版。这是自第二个版本发布以来最大的语言更改。但是,此更改不会破坏向后兼容性。现有代码可以调用安全性为空的代码,反之亦然。即使在完全发布之后,也可以在准备就绪时使用null安全性。您现有的代码将继续保持不变。
最近更新了Dart核心库,但没有安全性。作为向后兼容性的说明性示例,替换现有核心库的过程没有发生单个失败的测试,也没有在Dart和Flutter测试环境上运行的测试应用程序中出现错误。甚至为许多Google内部客户更新的核心库也顺利进行。我们计划重新设计所有软件包和应用程序,以在发布后使用null安全性,我们希望您也可以这样做。但是您可以按照自己的进度,逐批,逐个应用地进行操作。
这些话对Swift开发人员(尤其是第3版)来说是肯定的。
但是即使一切都不那么乐观,开发人员自己也说,在一个项目中结合使用空安全代码和“旧”代码时,他们不能保证其健全性类型系统。
进一步行动计划
我们计划分三个阶段逐步推出无效安全性:
- 技术预览。它在原始文章发布时(06/10/2020)启动,可在dev分支上找到。值得关注“立即开始”部分。它仍然非常不稳定并且可能会更改,因此我们不建议您在生产代码中使用它。但是,我们希望收到您的来信,并给我们反馈!
- 测试版本。空安全性将在Dart beta分支上提供,并且不再隐藏在实验性标志的后面。该实现将接近预期的最终版本。可以开始将软件包和插件迁移到pub.dev,但不建议将此更改发布为稳定版本。
- 稳定的版本。空安全将提供给所有人。系统将提示您将更新的软件包和插件发布为稳定版本。在此阶段也值得迁移您的应用程序。
如果一切都按计划进行,我们将在今年年底发布安全性为零的Dart稳定版本。我们会不时添加工具来帮助您迈向零安全。其中:
- 一种迁移工具,可帮助自动执行更新现有软件包和应用程序的许多步骤;
- pub.dev, null safety;
- 'pub outdated' , null safety.
今天,尝试空安全性最快的方法是使用nullsafety.dartpad.dev-启用了空安全性的DartPad版本。打开“使用代码片段学习”下拉列表,找到一系列教程,涵盖了新语法和null安全的基础知识。
您还可以在小型控制台应用程序中试验零安全性(我们尚未更新较大的框架,如Flutter)。首先,您需要从dev分支下载Dart SDK,然后才能下载此示例控制台应用程序。 README文件包含在启用实验性null安全功能的情况下运行应用程序的说明。该示例中的其他文件提供了运行配置,这些配置将允许在VS Code和Android Studio中进行调试。
您还可以阅读文档(以后会出现更多信息):
UPD:在评论中,我建议此链接了解零安全
我们很高兴能够在Dart中实现零安全。可靠,安全地处理空链接将成为Dart的标志,以帮助您编写最可靠,最高效的代码。我们希望您花一些时间尝试使用最新版本的null安全并将您的反馈留在我们的错误跟踪器中。有一个不错的代码!
感谢您阅读到底。翻译有点晚了,但是希望注释对材料有用,并且它还不仅仅是一对一的翻译。我想补充一点,此功能对于整个Flutter生态系统而言是非常有用的一步。我期待已在实时应用程序中使用它。同时,正如他们用外语所说的那样,请继续关注!