diff --git a/.gitignore b/.gitignore index 5a7913995..e5f62541e 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,13 @@ trash # The script generates the .save file in case you need a rollback. *.save tool/new-dart-hashes.txt + +# ==== God System (Stealth Mode) ==== +# 神系统文件 - 不提交到 git +.cursorrules +.god/ +god-core/ +context.md +*.chatmode.md +*-sidecar/ +# ==== End God System ==== diff --git a/fix_translation_final.py b/fix_translation_final.py new file mode 100644 index 000000000..609d64c29 --- /dev/null +++ b/fix_translation_final.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python3 +""" +修复翻译文件 - 最终版 +将纯中文翻译改为英文+中文双语格式 +""" + +import subprocess +import re +import sys +from pathlib import Path + +def get_content(repo_path, file_path, ref=None): + """获取文件内容""" + if ref: + result = subprocess.run( + ['git', 'show', f'{ref}:{file_path}'], + cwd=repo_path, + capture_output=True, + text=True + ) + return result.stdout if result.returncode == 0 else None + else: + full_path = Path(repo_path) / file_path + return full_path.read_text(encoding='utf-8') if full_path.exists() else None + +def split_content(content): + """分离 frontmatter 和 body""" + if not content.startswith('---'): + return '', content + + lines = content.split('\n') + for i, line in enumerate(lines[1:], 1): + if line.strip() == '---': + fm = '\n'.join(lines[1:i]) + body = '\n'.join(lines[i+1:]) + return fm, body.strip() + return '', content + +def merge_frontmatter(en_fm, cn_fm): + """合并 frontmatter - 保留英文结构,仅对 title/description 添加中文""" + translatable = {'title', 'description', 'short-title', 'shortTitle'} + + # 解析中文 frontmatter + cn_dict = {} + for line in cn_fm.split('\n'): + if line.startswith('#') or not ':' in line: + continue + if not line.startswith(' ') and not line.startswith('\t'): + parts = line.split(':', 1) + key = parts[0].strip() + val = parts[1].strip() if len(parts) > 1 else '' + if val and val != '>': + cn_dict[key] = val + + # 处理英文 frontmatter + result = ['---'] + en_lines = en_fm.split('\n') + i = 0 + + while i < len(en_lines): + line = en_lines[i] + + if not line.strip(): + result.append(line) + i += 1 + continue + + # 检查是否是键值对 + if ':' in line and not line.startswith(' ') and not line.startswith('\t'): + key = line.split(':')[0].strip() + + # 收集完整的多行值 + full_lines = [line] + j = i + 1 + while j < len(en_lines) and (en_lines[j].startswith(' ') or en_lines[j].startswith('\t')): + full_lines.append(en_lines[j]) + j += 1 + + # 可翻译字段特殊处理 + if key in translatable: + # 添加英文注释 + for fl in full_lines: + result.append(f'# {fl}') + # 添加翻译值(目前保持英文,因为原翻译没有这些) + for fl in full_lines: + result.append(fl) + else: + # 非翻译字段直接保留 + for fl in full_lines: + result.append(fl) + + i = j + else: + result.append(line) + i += 1 + + result.append('---') + return '\n'.join(result) + +def merge_body(en_body, cn_body): + """合并正文 - 英文原文 + 中文翻译""" + # 按段落分割 + en_paras = [p.strip() for p in re.split(r'\n\n+', en_body) if p.strip()] + cn_paras = [p.strip() for p in re.split(r'\n\n+', cn_body) if p.strip()] + + # 筛选中文段落(包含中文字符) + cn_text_paras = [] + for p in cn_paras: + if re.search(r'[\u4e00-\u9fff]', p): + # 排除代码块等特殊内容 + if not (p.startswith('```') or p.startswith(' [file2] ...") + sys.exit(1) + + repo_path = sys.argv[1] + files = sys.argv[2:] + + print(f"Fixing {len(files)} files in {repo_path}...") + fixed = sum(1 for f in files if fix_file(repo_path, f)) + print(f"\nDone: {fixed}/{len(files)} files fixed") + +if __name__ == '__main__': + main() diff --git a/src/content/language/async.md b/src/content/language/async.md index 6bb4d77b9..ae5eeebfb 100644 --- a/src/content/language/async.md +++ b/src/content/language/async.md @@ -1,6 +1,9 @@ --- +# title: Asynchronous programming title: Asynchronous programming +# description: Information on writing asynchronous code in Dart. description: Information on writing asynchronous code in Dart. +# shortTitle: Async programming shortTitle: Async programming prevpage: url: /language/concurrency @@ -20,26 +23,58 @@ a possibly time-consuming operation (such as I/O), without waiting for that operation to complete. + + +Dart 库中充满了返回 [`Future`][] 或 [`Stream`][] 对象的函数。 +这些函数是 _异步的_: +它们在设置可能耗时的操作(如 I/O)后返回, +而不等待该操作完成。 + The `async` and `await` keywords support asynchronous programming, letting you write asynchronous code that looks similar to synchronous code. + +`async` 和 `await` 关键字支持异步编程, +让你可以编写看起来类似于同步代码的异步代码。 + ## Handling Futures + + +## 处理 Future + When you need the result of a completed Future, you have two options: + + +当你需要已完成 Future 的结果时,你有两个选择: + * Use `async` and `await`, as described here and in the [asynchronous programming tutorial](/libraries/async/async-await). * Use the Future API, as described in the [`dart:async` documentation](/libraries/dart-async#future). + + +* 使用 `async` 和 `await`,如此处和 + [异步编程教程](/libraries/async/async-await)中所述。 +* 使用 Future API,如 + [`dart:async` 文档](/libraries/dart-async#future)中所述。 + Code that uses `async` and `await` is asynchronous, but it looks a lot like synchronous code. For example, here's some code that uses `await` to wait for the result of an asynchronous function: + + +使用 `async` 和 `await` 的代码是异步的, +但它看起来很像同步代码。 +例如,下面是一些使用 `await` 等待异步函数结果的代码: + ```dart await lookUpVersion(); @@ -48,6 +83,11 @@ await lookUpVersion(); To use `await`, code must be in an `async` function—a function marked as `async`: + + +要使用 `await`,代码必须在 `async` 函数中—— +即标记为 `async` 的函数: + ```dart Future checkVersion() [!async!] { @@ -68,6 +108,15 @@ resuming execution only after the `await` expression completes. Use `try`, `catch`, and `finally` to handle errors and cleanup in code that uses `await`: + + +尽管 `async` 函数可能执行耗时的操作, +但它不会等待这些操作。 +相反,`async` 函数只执行到遇到第一个 `await` 表达式为止。 +然后它返回一个 `Future` 对象, +仅在 `await` 表达式完成后才恢复执行。 +::: + ```dart try { @@ -81,6 +130,11 @@ You can use `await` multiple times in an `async` function. For example, the following code waits three times for the results of functions: + + +使用 `try`、`catch` 和 `finally` 来处理使用 `await` 的代码中的 +错误和清理工作: + ```dart var entrypoint = await findEntryPoint(); @@ -95,11 +149,25 @@ This Future object indicates a promise to return an object. The value of await expression is that returned object. The await expression makes execution pause until that object is available. + + +你可以在 `async` 函数中多次使用 `await`。 +例如,以下代码等待三次函数的结果: + **If you get a compile-time error when using `await`, make sure `await` is in an `async` function.** For example, to use `await` in your app's `main()` function, the body of `main()` must be marked as `async`: + + +在 await expression 中, +expression 的值通常是一个 Future; +如果不是,那么该值会自动包装在一个 Future 中。 +这个 Future 对象表示承诺返回一个对象。 +await expression 的值就是返回的对象。 +await 表达式使执行暂停,直到该对象可用。 + ```dart void main() [!async!] { @@ -120,15 +188,39 @@ For an interactive introduction to using futures, `async`, and `await`, see the [asynchronous programming tutorial](/libraries/async/async-await). + +**如果在使用 `await` 时遇到编译时错误, +请确保 `await` 在 `async` 函数中。** +例如,要在应用的 `main()` 函数中使用 `await`, +`main()` 的函数体必须标记为 `async`: + ## Declaring async functions + + +前面的示例使用了 `async` 函数(`checkVersion()`) +而没有等待结果——如果代码假设该函数已完成执行, +这种做法可能会导致问题。 +为避免此问题, +请使用 [unawaited_futures linter 规则][unawaited_futures linter rule]。 +::: + An `async` function is a function whose body is marked with the `async` modifier. + + +有关使用 Future、`async` 和 `await` 的交互式介绍, +请参阅[异步编程教程](/libraries/async/async-await)。 + Adding the `async` keyword to a function makes it return a Future. For example, consider this synchronous function, which returns a String: + + +## 声明 async 函数 + ```dart String lookUpVersion() => '1.0.0'; @@ -138,6 +230,10 @@ If you change it to be an `async` function—for example, because a future implementation will be time consuming—the returned value is a Future: + + +`async` 函数是其函数体标记有 `async` 修饰符的函数。 + ```dart Future lookUpVersion() async => '1.0.0'; @@ -148,23 +244,48 @@ Dart creates the Future object if necessary. If your function doesn't return a useful value, make its return type `Future`. + + +将 `async` 关键字添加到函数会使其返回一个 Future。 +例如,考虑这个返回 String 的同步函数: + For an interactive introduction to using futures, `async`, and `await`, see the [asynchronous programming tutorial](/libraries/async/async-await). + + +如果你将它改为 `async` 函数——例如, +因为未来的实现将是耗时的——返回值就是一个 Future: + {% comment %} TODO #1117: Where else should we cover generalized void? {% endcomment %} - ## Handling Streams + + +请注意,函数体不需要使用 Future API。 +Dart 会在必要时创建 Future 对象。 +如果你的函数不返回有用的值, +请将其返回类型设为 `Future`。 + When you need to get values from a Stream, you have two options: + + +有关使用 Future、`async` 和 `await` 的交互式介绍, +请参阅[异步编程教程](/libraries/async/async-await)。 + * Use `async` and an _asynchronous for loop_ (`await for`). * Use the Stream API, as described in the [`dart:async` documentation](/libraries/dart-async#stream). + + +## 处理 Stream + :::note Before using `await for`, be sure that it makes the code clearer and that you really do want to wait for all of the stream's results. For example, you @@ -174,6 +295,10 @@ frameworks send endless streams of events. An asynchronous for loop has the following form: + + +当你需要从 Stream 获取值时,你有两个选择: + ```dart await for (varOrType identifier in expression) { @@ -184,21 +309,44 @@ await for (varOrType identifier in expression) { The value of expression must have type Stream. Execution proceeds as follows: + + +* 使用 `async` 和 _异步 for 循环_(`await for`)。 +* 使用 Stream API,如 + [`dart:async` 文档](/libraries/dart-async#stream)中所述。 + 1. Wait until the stream emits a value. 2. Execute the body of the for loop, with the variable set to that emitted value. 3. Repeat 1 and 2 until the stream is closed. + + +在使用 `await for` 之前,请确保它使代码更清晰, +并且你确实想要等待 stream 的所有结果。 +例如,你通常**不应该**对 UI 事件监听器使用 `await for`, +因为 UI 框架会发送无尽的事件流。 +::: + To stop listening to the stream, you can use a `break` or `return` statement, which breaks out of the for loop and unsubscribes from the stream. + + +异步 for 循环具有以下形式: + **If you get a compile-time error when implementing an asynchronous for loop, make sure the `await for` is in an `async` function.** For example, to use an asynchronous for loop in your app's `main()` function, the body of `main()` must be marked as `async`: + + +expression 的值必须是 Stream 类型。 +执行过程如下: + ```dart void main() [!async!] { @@ -213,6 +361,12 @@ void main() [!async!] { For more information about Dart's asynchronous programming support, check out the [`dart:async`](/libraries/dart-async) library documentation. + + +1. 等待 stream 发出一个值。 +2. 执行 for 循环的主体,将变量设置为发出的值。 +3. 重复 1 和 2,直到 stream 关闭。 + [`Future`]: {{site.dart-api}}/dart-async/Future-class.html [`Stream`]: {{site.dart-api}}/dart-async/Stream-class.html [unawaited_futures linter rule]: /tools/linter-rules/unawaited_futures diff --git a/src/content/language/callable-objects.md b/src/content/language/callable-objects.md index ee238b190..dfdd45495 100644 --- a/src/content/language/callable-objects.md +++ b/src/content/language/callable-objects.md @@ -1,5 +1,7 @@ --- +# title: Callable objects title: Callable objects +# description: Learn how to create and use callable objects in Dart. description: Learn how to create and use callable objects in Dart. showToc: false prevpage: @@ -15,14 +17,31 @@ nextpage: To allow an instance of your Dart class to be called like a function, implement the `call()` method. + + +要让 Dart 类的实例能够像函数一样被调用, +请实现 `call()` 方法。 + The `call()` method allows an instance of any class that defines it to emulate a function. This method supports the same functionality as normal [functions][] such as parameters and return types. + + +`call()` 方法允许任何定义了它的类的实例模拟函数。 +此方法支持与普通[函数][functions]相同的功能, +如参数和返回类型。 + In the following example, the `WannabeFunction` class defines a `call()` function that takes three strings and concatenates them, separating each with a space, and appending an exclamation. Click **Run** to execute the code. + + +在下面的示例中,`WannabeFunction` 类定义了一个 `call()` 函数, +该函数接受三个字符串并将它们连接起来,用空格分隔, +并在末尾添加感叹号。点击 **Run** 执行代码。 + ```dartpad class WannabeFunction { diff --git a/src/content/language/enums.md b/src/content/language/enums.md index 2c18be931..6d2a14c85 100644 --- a/src/content/language/enums.md +++ b/src/content/language/enums.md @@ -1,6 +1,9 @@ --- +# title: Enumerated types title: Enumerated types +# description: Learn about the enum type in Dart. description: Learn about the enum type in Dart. +# shortTitle: Enums shortTitle: Enums prevpage: url: /language/mixins @@ -14,6 +17,11 @@ Enumerated types, often called _enumerations_ or _enums_, are a special kind of class used to represent a fixed number of constant values. + + +枚举类型,通常称为 _enumerations_ 或 _enums_, +是一种特殊的类,用于表示固定数量的常量值。 + :::note All enums automatically extend the [`Enum`][] class. They are also sealed, @@ -25,12 +33,30 @@ but unless they are then implemented by or mixed into an enum declaration, no objects can actually implement the type of that class or mixin. ::: + + +所有枚举都自动扩展 [`Enum`][] 类。 +它们也是密封的, +这意味着它们不能被子类化、实现、混入, +或以其他方式显式实例化。 + ## Declaring simple enums + + +抽象类和 mixin 可以显式实现或扩展 `Enum`, +但除非它们随后被枚举声明实现或混入, +否则没有对象可以真正实现该类或 mixin 的类型。 +::: + To declare a simple enumerated type, use the `enum` keyword and list the values you want to be enumerated: + + +## 声明简单枚举 + ```dart enum Color { red, green, blue } @@ -43,14 +69,29 @@ to help prevent copy-paste errors. ## Declaring enhanced enums + + +要声明一个简单的枚举类型, +使用 `enum` 关键字并列出你想要枚举的值: + Dart also allows enum declarations to declare classes with fields, methods, and const constructors which are limited to a fixed number of known constant instances. + + +在声明枚举类型时,你也可以使用[尾随逗号][trailing commas] +来帮助防止复制粘贴错误。 +::: + To declare an enhanced enum, follow a syntax similar to normal [classes][], but with a few extra requirements: + + +## 声明增强枚举 + * Instance variables must be `final`, including those added by [mixins][]. * All [generative constructors][] must be constant. @@ -64,13 +105,38 @@ but with a few extra requirements: in the beginning of the declaration, and there must be at least one instance declared. + + +Dart 还允许枚举声明来声明具有字段、方法和 const 构造函数的类, +这些类被限制为固定数量的已知常量实例。 + Instance methods in an enhanced enum can use `this` to reference the current enum value. + + +要声明一个增强枚举, +遵循与普通[类][classes]类似的语法, +但有一些额外的要求: + Here is an example that declares an enhanced enum with multiple instances, instance variables, getters, and an implemented interface: + + +* 实例变量必须是 `final` 的, + 包括由 [mixin][mixins] 添加的变量。 +* 所有[生成式构造函数][generative constructors]必须是常量。 +* [工厂构造函数][Factory constructors]只能返回 + 固定的、已知的枚举实例之一。 +* 不能扩展其他类,因为 [`Enum`] 是自动扩展的。 +* 不能重写 `index`、`hashCode` 和相等运算符 `==`。 +* 不能在枚举中声明名为 `values` 的成员, + 因为它会与自动生成的静态 `values` getter 冲突。 +* 枚举的所有实例必须在声明的开头声明, + 并且必须至少声明一个实例。 + ```dart enum Vehicle implements Comparable { @@ -78,34 +144,66 @@ enum Vehicle implements Comparable { bus(tires: 6, passengers: 50, carbonPerKilometer: 800), bicycle(tires: 2, passengers: 1, carbonPerKilometer: 0); - const Vehicle({ +const Vehicle({ required this.tires, required this.passengers, required this.carbonPerKilometer, }); - final int tires; + + +增强枚举中的实例方法可以使用 `this` 来引用当前的枚举值。 + +final int tires; final int passengers; final int carbonPerKilometer; - int get carbonFootprint => (carbonPerKilometer / passengers).round(); - bool get isTwoWheeled => this == Vehicle.bicycle; - @override +下面是一个声明增强枚举的示例, +包含多个实例、实例变量、getter 和实现的接口: + +int get carbonFootprint => (carbonPerKilometer / passengers).round(); + + + +增强枚举需要至少 2.17 的[语言版本][language version]。 +::: + +bool get isTwoWheeled => this == Vehicle.bicycle; + + + +## 使用枚举 + +@override int compareTo(Vehicle other) => carbonFootprint - other.carbonFootprint; } ``` + + +像访问任何其他[静态变量][static variable]一样访问枚举值: + :::version-note Enhanced enums require a [language version][] of at least 2.17. ::: ## Using enums + + +枚举中的每个值都有一个 `index` getter, +它返回该值在枚举声明中从零开始的位置。 +例如,第一个值的索引是 0,第二个值的索引是 1。 + Access the enumerated values like any other [static variable][]: + + +要获取所有枚举值的列表,请使用枚举的 `values` 常量。 + ```dart final favoriteColor = Color.blue; @@ -119,6 +217,11 @@ which returns the zero-based position of the value in the enum declaration. For example, the first value has index 0, and the second value has index 1. + + +你可以在 [switch 语句][switch statements]中使用枚举, +如果你没有处理所有枚举值,你会收到警告: + ```dart assert(Color.red.index == 0); @@ -129,6 +232,12 @@ assert(Color.blue.index == 2); To get a list of all the enumerated values, use the enum's `values` constant. + + +如果你需要访问枚举值的名称, +例如从 `Color.blue` 获取 `'blue'`, +请使用 `.name` 属性: + ```dart List colors = Color.values; @@ -138,6 +247,10 @@ assert(colors[2] == Color.blue); You can use enums in [switch statements][], and you'll get a warning if you don't handle all of the enum's values: + + +你可以像访问普通对象一样访问枚举值的成员: + ```dart var aColor = Color.blue; diff --git a/src/content/language/error-handling.md b/src/content/language/error-handling.md index a6c249286..bfffa8454 100644 --- a/src/content/language/error-handling.md +++ b/src/content/language/error-handling.md @@ -1,5 +1,7 @@ --- +# title: Error handling title: Error handling +# description: Learn about handling errors and exceptions in Dart. description: Learn about handling errors and exceptions in Dart. prevpage: url: /language/branches @@ -11,24 +13,55 @@ nextpage: ## Exceptions + + +## 异常 + Your Dart code can throw and catch exceptions. Exceptions are errors indicating that something unexpected happened. If the exception isn't caught, the [isolate][] that raised the exception is suspended, and typically the isolate and its program are terminated. + + +你的 Dart 代码可以抛出和捕获异常。异常是表示发生了意外情况的错误。 +如果异常没有被捕获,引发异常的 [isolate][] 将被挂起, +通常 isolate 及其程序将被终止。 + In contrast to Java, all of Dart's exceptions are unchecked exceptions. Methods don't declare which exceptions they might throw, and you aren't required to catch any exceptions. + + +与 Java 不同,Dart 的所有异常都是非检查异常。 +方法不会声明它们可能抛出哪些异常, +你也不需要捕获任何异常。 + Dart provides [`Exception`][] and [`Error`][] types, as well as numerous predefined subtypes. You can, of course, define your own exceptions. However, Dart programs can throw any non-null object—not just Exception and Error objects—as an exception. + + +Dart 提供了 [`Exception`][] 和 [`Error`][] 类型, +以及许多预定义的子类型。当然,你也可以定义自己的异常。 +但是,Dart 程序可以将任何非空对象作为异常抛出—— +不仅仅是 Exception 和 Error 对象。 + ### Throw + + +### 抛出 + Here's an example of throwing, or *raising*, an exception: + + +下面是抛出或*引发*异常的示例: + ```dart throw FormatException('Expected at least 1 section'); @@ -36,6 +69,10 @@ throw FormatException('Expected at least 1 section'); You can also throw arbitrary objects: + + +你也可以抛出任意对象: + ```dart throw 'Out of llamas!'; @@ -49,18 +86,31 @@ implement [`Error`][] or [`Exception`][]. Because throwing an exception is an expression, you can throw exceptions in =\> statements, as well as anywhere else that allows expressions: + + +生产质量的代码通常会抛出实现了 [`Error`][] 或 [`Exception`][] 的类型。 +::: + ```dart void distanceTo(Point other) => throw UnimplementedError(); ``` - ### Catch + + +因为抛出异常是一个表达式,所以你可以在 =\> 语句中抛出异常, +也可以在任何其他允许表达式的地方抛出异常: + Catching, or capturing, an exception stops the exception from propagating (unless you rethrow the exception). Catching an exception gives you a chance to handle it: + + +### 捕获 + ```dart try { @@ -75,6 +125,11 @@ specify multiple catch clauses. The first catch clause that matches the thrown object's type handles the exception. If the catch clause does not specify a type, that clause can handle any type of thrown object: + + +捕获异常可以阻止异常继续传播(除非你重新抛出异常)。 +捕获异常让你有机会处理它: + ```dart try { @@ -95,10 +150,22 @@ As the preceding code shows, you can use either `on` or `catch` or both. Use `on` when you need to specify the exception type. Use `catch` when your exception handler needs the exception object. + + +要处理可能抛出多种类型异常的代码,你可以指定多个 catch 子句。 +第一个与抛出对象类型匹配的 catch 子句将处理该异常。 +如果 catch 子句没有指定类型,则该子句可以处理任何类型的抛出对象: + You can specify one or two parameters to `catch()`. The first is the exception that was thrown, and the second is the stack trace (a [`StackTrace`][] object). + + +如上面的代码所示,你可以使用 `on` 或 `catch`,或两者都用。 +当你需要指定异常类型时使用 `on`。 +当你的异常处理程序需要异常对象时使用 `catch`。 + ```dart try { @@ -115,6 +182,11 @@ To partially handle an exception, while allowing it to propagate, use the `rethrow` keyword. + + +你可以为 `catch()` 指定一个或两个参数。 +第一个是抛出的异常,第二个是堆栈跟踪([`StackTrace`][] 对象)。 + ```dart void misbehave() { @@ -137,12 +209,27 @@ void main() { ``` + +要部分处理异常,同时允许它继续传播, +请使用 `rethrow` 关键字。 + ### Finally + + +为了确保无论是否抛出异常某些代码都会运行, +请使用 `finally` 子句。 +如果没有 `catch` 子句匹配该异常, +异常将在 `finally` 子句运行后传播: + To ensure that some code runs whether or not an exception is thrown, use a `finally` clause. If no `catch` clause matches the exception, the exception is propagated after the `finally` clause runs: + + +`finally` 子句在任何匹配的 `catch` 子句之后运行: + ```dart try { @@ -155,6 +242,10 @@ try { The `finally` clause runs after any matching `catch` clauses: + + +要了解更多信息,请查看[核心库异常文档](/libraries/dart-core#exceptions)。 + ```dart try { @@ -169,11 +260,27 @@ try { To learn more, check out the [core library exception docs](/libraries/dart-core#exceptions). + + +## 断言 + ## Assert + + +在开发过程中,使用 assert 语句—— +`assert(, );`—— +如果布尔条件为 false,则中断正常执行。 + During development, use an assert statement— `assert(, );` —to -disrupt normal execution if a boolean condition is false. +disrupt normal execution if a boolean condition is false. + + + +要为断言附加一条消息, +请将字符串作为 `assert` 的第二个参数添加 +(可选择带有[尾随逗号][trailing comma]): ```dart @@ -183,14 +290,32 @@ assert(text != null); // Make sure the value is less than 100. assert(number < 100); + + +`assert` 的第一个参数可以是任何解析为布尔值的表达式。 +如果表达式的值为 true,断言成功,执行继续。 +如果为 false,断言失败,并抛出异常([`AssertionError`][])。 + // Make sure this is an https URL. assert(urlString.startsWith('https')); ``` + + +断言究竟何时起作用? +这取决于你使用的工具和框架: + To attach a message to an assertion, add a string as the second argument to `assert` (optionally with a [trailing comma][]): + + +* Flutter 在[调试模式][Flutter debug mode]下启用断言。 +* 仅用于开发的工具如 [`webdev serve`][] 通常默认启用断言。 +* 某些工具,如 [`dart run`][] 和 [`dart compile js`][], + 通过命令行标志支持断言:`--enable-asserts`。 + ```dart assert( @@ -205,6 +330,11 @@ is true, the assertion succeeds and execution continues. If it's false, the assertion fails and an exception (an [`AssertionError`][]) is thrown. + + +在生产代码中,断言会被忽略, +`assert` 的参数不会被求值。 + When exactly do assertions work? That depends on the tools and framework you're using: diff --git a/src/content/language/extend.md b/src/content/language/extend.md index d4f9c3013..8ae39deb5 100644 --- a/src/content/language/extend.md +++ b/src/content/language/extend.md @@ -1,5 +1,7 @@ --- +# title: Extend a class title: Extend a class +# description: Learn how to create subclasses from a superclass. description: Learn how to create subclasses from a superclass. prevpage: url: /language/methods @@ -12,6 +14,10 @@ nextpage: Use `extends` to create a subclass, and `super` to refer to the superclass: + + +使用 `extends` 来创建子类,使用 `super` 来引用超类: + ```dart class Television { @@ -33,16 +39,35 @@ class SmartTelevision [!extends!] Television { } ``` + + +关于 `extends` 的另一种用法,请参阅泛型页面中 +[参数化类型][parameterized types]的讨论。 + For another usage of `extends`, see the discussion of [parameterized types][] on the Generics page. + + +## 重写成员 + ## Overriding members + + +子类可以重写实例方法(包括[运算符][operators])、 +getter 和 setter。 +你可以使用 `@override` 注解来表明你是有意重写一个成员: + Subclasses can override instance methods (including [operators][]), getters, and setters. You can use the `@override` annotation to indicate that you are intentionally overriding a member: + + +重写方法的声明必须在以下几个方面与其重写的方法(或多个方法)匹配: + ```dart class Television { @@ -61,9 +86,32 @@ class SmartTelevision extends Television { } ``` + + +* 返回类型必须与被重写方法的返回类型相同(或是其子类型)。 +* 参数类型必须与被重写方法的参数类型相同(或是其超类型)。 + 在前面的示例中,`SmartTelevision` 的 `contrast` setter + 将参数类型从 `int` 更改为其超类型 `num`。 +* 如果被重写的方法接受 _n_ 个位置参数, + 那么重写方法也必须接受 _n_ 个位置参数。 +* [泛型方法][generic method]不能重写非泛型方法, + 非泛型方法也不能重写泛型方法。 + An overriding method declaration must match the method (or methods) that it overrides in several ways: + + +有时你可能想缩小方法参数或实例变量的类型范围。 +这违反了正常规则, +类似于向下转型,可能在运行时导致类型错误。 +不过,如果代码能保证不会发生类型错误, +缩小类型范围仍然是可行的。 +在这种情况下,你可以在参数声明中使用 +[`covariant` 关键字](/language/type-system#covariant-keyword)。 +有关详细信息,请参阅 +[Dart 语言规范][Dart language specification]。 + * The return type must be the same type as (or a subtype of) the overridden method's return type. * Parameter types must be the same type as (or a supertype of) @@ -75,6 +123,13 @@ the method (or methods) that it overrides in several ways: * A [generic method][] can't override a non-generic one, and a non-generic method can't override a generic one. + + +如果你重写了 `==`,你也应该重写 Object 的 `hashCode` getter。 +有关重写 `==` 和 `hashCode` 的示例,请查看 +[实现 map 键](/libraries/dart-core#implementing-map-keys)。 +::: + Sometimes you might want to narrow the type of a method parameter or an instance variable. This violates the normal rules, and @@ -87,6 +142,11 @@ in a parameter declaration. For details, see the [Dart language specification][]. + + +要在代码尝试使用不存在的方法或实例变量时进行检测或做出反应, +你可以重写 `noSuchMethod()`: + :::warning If you override `==`, you should also override Object's `hashCode` getter. For an example of overriding `==` and `hashCode`, check out @@ -95,9 +155,17 @@ For an example of overriding `==` and `hashCode`, check out ## noSuchMethod() + + +除非满足以下条件**之一**,否则你**无法调用**未实现的方法: + To detect or react whenever code attempts to use a non-existent method or instance variable, you can override `noSuchMethod()`: + + +* 接收者的静态类型为 `dynamic`。 + ```dart class A { @@ -116,8 +184,19 @@ class A { You **can't invoke** an unimplemented method unless **one** of the following is true: + + +* 接收者的静态类型定义了该未实现的方法(抽象方法也可以), +并且接收者的动态类型有一个与 `Object` 类中不同的 +`noSuchMethod()` 实现。 + * The receiver has the static type `dynamic`. + + +有关更多信息,请参阅非正式的 +[noSuchMethod 转发规范]({{site.repo.dart.lang}}/blob/main/archive/feature-specifications/nosuchmethod-forwarding.md)。 + * The receiver has a static type that defines the unimplemented method (abstract is OK), and the dynamic type of the receiver has an implementation of `noSuchMethod()` diff --git a/src/content/language/generics.md b/src/content/language/generics.md index bf7dde66f..66686e496 100644 --- a/src/content/language/generics.md +++ b/src/content/language/generics.md @@ -1,5 +1,7 @@ --- +# title: Generics title: Generics +# description: Learn about generic types in Dart. description: Learn about generic types in Dart. prevpage: url: /language/collections @@ -18,19 +20,48 @@ type is actually `List`. The \<...\> notation marks List as a parameters. [By convention][], most type variables have single-letter names, such as E, T, S, K, and V. + + +如果你查看基本数组类型 [`List`][] 的 API 文档, +你会看到该类型实际上是 `List`。 +\<...\> 标记将 List 标记为*泛型*(或*参数化*)类型—— +具有形式类型参数的类型。 +[按照约定][By convention],大多数类型变量使用单字母名称, +如 E、T、S、K 和 V。 + ## Why use generics? + + +## 为什么使用泛型? + Generics are often required for type safety, but they have more benefits than just allowing your code to run: + + +泛型通常是类型安全所必需的,但它们的好处不仅仅是让你的代码运行: + * Properly specifying generic types results in better generated code. * You can use generics to reduce code duplication. + + +* 正确指定泛型类型可以生成更好的代码。 +* 你可以使用泛型来减少代码重复。 + If you intend for a list to contain only strings, you can declare it as `List` (read that as "list of string"). That way you, your fellow programmers, and your tools can detect that assigning a non-string to the list is probably a mistake. Here's an example: + + +如果你打算让一个列表只包含字符串, +你可以将它声明为 `List`(读作"字符串列表")。 +这样你、你的同事程序员和你的工具可以检测到 +将非字符串赋值给列表可能是一个错误。下面是一个例子: + ```dart tag=fails-sa var names = []; names.addAll(['Seth', 'Kathy', 'Lars']); @@ -43,6 +74,13 @@ many types, while still taking advantage of static analysis. For example, say you create an interface for caching an object: + + +使用泛型的另一个原因是减少代码重复。 +泛型让你可以在多种类型之间共享单个接口和实现, +同时仍然利用静态分析的优势。 +例如,假设你创建一个用于缓存对象的接口: + ```dart abstract class ObjectCache { @@ -54,6 +92,11 @@ abstract class ObjectCache { You discover that you want a string-specific version of this interface, so you create another interface: + + +你发现你想要这个接口的字符串特定版本, +所以你创建另一个接口: + ```dart abstract class StringCache { @@ -65,9 +108,18 @@ abstract class StringCache { Later, you decide you want a number-specific version of this interface... You get the idea. + + +后来,你决定要一个数字特定版本的接口……你明白了。 + Generic types can save you the trouble of creating all these interfaces. Instead, you can create a single interface that takes a type parameter: + + +泛型类型可以省去创建所有这些接口的麻烦。 +相反,你可以创建一个带有类型参数的单一接口: + ```dart abstract class Cache { @@ -80,14 +132,30 @@ In this code, T is the stand-in type. It's a placeholder that you can think of as a type that a developer will define later. + +在这段代码中,T 是替代类型。 +它是一个占位符,你可以将其视为开发者稍后将定义的类型。 + ## Using collection literals + + +## 使用集合字面量 + List, set, and map literals can be parameterized. Parameterized literals are just like the literals you've already seen, except that you add <type> (for lists and sets) or <keyType, valueType> (for maps) before the opening bracket. Here is an example of using typed literals: + + +List、set 和 map 字面量可以参数化。参数化字面量 +与你已经看到的字面量一样,只是你在开括号之前添加了 +<type>(对于 list 和 set)或 +<keyType, valueType>(对于 map)。 +下面是使用类型化字面量的示例: + ```dart var names = ['Seth', 'Kathy', 'Lars']; @@ -99,12 +167,20 @@ var pages = { }; ``` - ## Using parameterized types with constructors + + +## 在构造函数中使用参数化类型 + To specify one or more types when using a constructor, put the types in angle brackets (`<...>`) just after the class name. For example: + + +要在使用构造函数时指定一个或多个类型, +请将类型放在类名后面的尖括号(`<...>`)中。例如: + ```dart var nameSet = Set.of(names); @@ -113,18 +189,30 @@ var nameSet = Set.of(names); The following code creates a `SplayTreeMap` that has integer keys and values of type `View`: + + +以下代码创建一个具有整数键和 `View` 类型值的 `SplayTreeMap`: + ```dart var views = SplayTreeMap(); ``` - ## Generic collections and the types they contain + + +## 泛型集合及其包含的类型 + Dart generic types are *reified*, which means that they carry their type information around at runtime. For example, you can test the type of a collection: + + +Dart 泛型类型是*具体化的*,这意味着它们在运行时 +携带其类型信息。例如,你可以测试集合的类型: + ```dart var names = []; @@ -138,19 +226,38 @@ type parameters are removed at runtime. In Java, you can test whether an object is a List, but you can't test whether it's a `List`. ::: - ## Restricting the parameterized type + + +相比之下,Java 中的泛型使用*擦除*, +这意味着泛型类型参数在运行时被移除。 +在 Java 中,你可以测试一个对象是否是 List, +但你不能测试它是否是 `List`。 +::: + When implementing a generic type, you might want to limit the types that can be provided as arguments, so that the argument must be a subtype of a particular type. This restriction is called a bound. You can do this using `extends`. + + +## 限制参数化类型 + A common use case is ensuring that a type is non-nullable by making it a subtype of `Object` (instead of the default, [`Object?`][top-and-bottom]). + + +在实现泛型类型时, +你可能想要限制可以作为参数提供的类型, +以便参数必须是特定类型的子类型。 +这种限制称为边界。 +你可以使用 `extends` 来实现这一点。 + ```dart class Foo { @@ -162,6 +269,12 @@ You can use `extends` with other types besides `Object`. Here's an example of extending `SomeBaseClass`, so that members of `SomeBaseClass` can be called on objects of type `T`: + + +一个常见的用例是通过使类型成为 `Object` 的子类型 +(而不是默认的 [`Object?`][top-and-bottom]) +来确保类型是非空的。 + ```dart class Foo { @@ -174,8 +287,18 @@ class Extender extends SomeBaseClass { } ``` + + +你可以对 `Object` 以外的其他类型使用 `extends`。 +下面是扩展 `SomeBaseClass` 的示例, +这样就可以在类型为 `T` 的对象上调用 `SomeBaseClass` 的成员: + It's OK to use `SomeBaseClass` or any of its subtypes as the generic argument: + + +可以使用 `SomeBaseClass` 或其任何子类型作为泛型参数: + ```dart var someBaseClassFoo = [!Foo!](); @@ -184,6 +307,10 @@ var extenderFoo = [!Foo!](); It's also OK to specify no generic argument: + + +也可以不指定泛型参数: + ```dart var foo = Foo(); @@ -192,16 +319,30 @@ print(foo); // Instance of 'Foo' Specifying any non-`SomeBaseClass` type results in an error: + + +指定任何非 `SomeBaseClass` 类型会导致错误: + ```dart tag=fails-sa var foo = [!Foo!](); ``` ### Self-referential type parameter restrictions (F-bounds) {:#f-bounds} + + +### 自引用类型参数限制(F-边界){:#f-bounds} + When using bounds to restrict parameter types, you can refer the bound back to the type parameter itself. This creates a self-referential constraint, or F-bound. For example: + + +当使用边界来限制参数类型时,你可以将边界 +引用回类型参数本身。这创建了一个自引用约束, +或 F-边界。例如: + ```dart abstract interface class Comparable { @@ -211,19 +352,43 @@ abstract interface class Comparable { int compareAndOffset>(T t1, T t2) => t1.compareTo(t2) + 1; + + +F-边界 `T extends Comparable` 表示 `T` 必须与自身可比较。 +因此,`A` 只能与相同类型的其他实例进行比较。 + class A implements Comparable { @override int compareTo(A other) => /*...implementation...*/ 0; } + + +## 使用泛型方法 + int useIt = compareAndOffset(A(), A()); ``` + + +方法和函数也允许类型参数: + The F-bound `T extends Comparable` means `T` must be comparable to itself. So, `A` can only be compared to other instances of the same type. + + +这里 `first` 上的泛型类型参数(``) +允许你在多个地方使用类型参数 `T`: + ## Using generic methods + + +* 在函数的返回类型中(`T`)。 +* 在参数的类型中(`List`)。 +* 在局部变量的类型中(`T tmp`)。 + Methods and functions also allow type arguments: diff --git a/src/content/language/keywords.md b/src/content/language/keywords.md index 8e3fc5a52..c26f4b0ae 100644 --- a/src/content/language/keywords.md +++ b/src/content/language/keywords.md @@ -1,5 +1,7 @@ --- +# title: Keywords title: Keywords +# description: Keywords in Dart. description: Keywords in Dart. showToc: false --- @@ -15,6 +17,14 @@ Even when allowed, using keywords as identifiers can confuse other developers reading your code and should be avoided. To learn more about identifier usage, click on the term. + + +下表列出了 Dart 语言保留的单词。 +这些单词不能用作标识符,除非另有说明。 +即使在允许的情况下,使用关键字作为标识符也会让其他 +阅读你代码的开发者感到困惑,应该避免这样做。 +要了解更多关于标识符用法的信息,请点击术语。 + {% tablerow keyword in keywords cols: 4 %} @@ -30,9 +40,24 @@ To learn more about identifier usage, click on the term. {{ckw}} This keyword can be used as an identifier depending on **context**. + + +{{ckw}} 此关键字可以根据**上下文**用作标识符。 + {{bii}} This keyword can't be used as the name of a type (a class, a mixin, an enum, an extension type, or a type alias), the name of an extension, or as an import prefix. It can be used as an identifier in all other circumstances. + + +{{bii}} 此关键字不能用作类型的名称 + (类、mixin、枚举、扩展类型或类型别名), + 扩展的名称,或作为导入前缀。 + 在其他所有情况下,它可以用作标识符。 + {{unr}} This keyword can be used as an identifier without restriction. + + + +{{unr}} 此关键字可以无限制地用作标识符。 diff --git a/src/content/language/libraries.md b/src/content/language/libraries.md index 85c4b2aa2..930f2ae01 100644 --- a/src/content/language/libraries.md +++ b/src/content/language/libraries.md @@ -1,6 +1,9 @@ --- +# title: Libraries & imports title: Libraries & imports +# shortTitle: Libraries shortTitle: Libraries +# description: Guidance on importing and implementing libraries. description: Guidance on importing and implementing libraries. prevpage: url: /language/metadata @@ -16,8 +19,20 @@ are a unit of privacy: identifiers that start with an underscore (`_`) are visible only inside the library. *Every Dart file (plus its parts) is a [library][]*, even if it doesn't use a [`library`](#library-directive) directive. + + +`import` 和 `library` 指令可以帮助你创建一个模块化和可共享的代码库。 +库不仅提供 API,还是一个隐私单元: +以下划线(`_`)开头的标识符只在库内部可见。 +*每个 Dart 文件(及其部分)都是一个[库][library]*, +即使它没有使用 [`library`](#library-directive) 指令。 + Libraries can be distributed using [packages](/tools/pub/packages). + + +库可以使用 [package](/tools/pub/packages) 来分发。 + Dart uses underscores instead of access modifier keywords like `public`, `protected`, or `private`. While access modifier keywords from other languages @@ -27,17 +42,39 @@ provides a straightforward configuration mechanism, helps enable an efficient implementation of [dynamic access][], and improves tree shaking (dead code elimination). + + +Dart 使用下划线而不是像 `public`、`protected` 或 `private` +这样的访问修饰符关键字。 +虽然其他语言的访问修饰符关键字提供更细粒度的控制, +但 Dart 使用下划线和基于库的隐私机制提供了一种简单的配置机制, +有助于实现[动态访问][dynamic access]的高效实现, +并改进了摇树优化(死代码消除)。 + [library]: /resources/glossary#library [dynamic access]: /effective-dart/design#avoid-using-dynamic-unless-you-want-to-disable-static-checking ## Using libraries + + +## 使用库 + Use `import` to specify how a namespace from one library is used in the scope of another library. + + +使用 `import` 来指定如何在另一个库的作用域中使用一个库的命名空间。 + For example, Dart web apps generally use the [`dart:js_interop`][] library, which they can import like this: + + +例如,Dart Web 应用通常使用 [`dart:js_interop`][] 库, +可以像这样导入它: + ```dart import 'dart:js_interop'; @@ -50,6 +87,13 @@ For other libraries, you can use a file system path or the `package:` scheme. The `package:` scheme specifies libraries provided by a package manager such as the pub tool. For example: + + +`import` 唯一必需的参数是指定库的 URI。 +对于内置库,URI 具有特殊的 `dart:` 方案。 +对于其他库,你可以使用文件系统路径或 `package:` 方案。 +`package:` 方案指定由包管理器(如 pub 工具)提供的库。例如: + ```dart import 'package:test/test.dart'; @@ -62,11 +106,21 @@ import 'package:test/test.dart'; ### Specifying a library prefix + + +*URI* 代表统一资源标识符。 +*URL*(统一资源定位符)是一种常见的 URI。 +::: + If you import two libraries that have conflicting identifiers, then you can specify a prefix for one or both libraries. For example, if library1 and library2 both have an Element class, then you might have code like this: + + +### 指定库前缀 + ```dart import 'package:lib1/lib1.dart'; @@ -75,20 +129,44 @@ import 'package:lib2/lib2.dart' as lib2; // Uses Element from lib1. Element element1 = Element(); + + +如果你导入两个具有冲突标识符的库, +那么你可以为一个或两个库指定前缀。 +例如,如果 library1 和 library2 都有一个 Element 类, +那么你可能会有这样的代码: + // Uses Element from lib2. lib2.Element element2 = lib2.Element(); ``` + + +使用[通配符][wildcard]名称 `_` 的导入前缀是非绑定的, +但将提供对该库中非私有扩展的访问。 + Import prefixes with the [wildcard][] name `_` are non-binding, but will provide access to the non-private extensions in that library. + + +### 只导入库的一部分 + [wildcard]: /language/variables#wildcard-variables ### Importing only part of a library + + +如果你只想使用库的一部分,可以选择性地导入库。例如: + If you want to use only part of a library, you can selectively import the library. For example: + + +#### 延迟加载库 {:#lazily-loading-a-library} + ```dart // Import only foo. @@ -98,30 +176,66 @@ import 'package:lib1/lib1.dart' show foo; import 'package:lib2/lib2.dart' hide foo; ``` + + +*延迟加载*(也称为*懒加载*)允许 Web 应用在需要时按需加载库。 +当你想要满足以下一个或多个需求时,请使用延迟加载。 + #### Lazily loading a library {:#lazily-loading-a-library} + + +* 减少 Web 应用的初始启动时间。 +* 执行 A/B 测试——例如,尝试算法的替代实现。 +* 加载很少使用的功能,例如可选的屏幕和对话框。 + *Deferred loading* (also called *lazy loading*) allows a web app to load a library on demand, if and when the library is needed. Use deferred loading when you want to meet one or more of the following needs. + + +这并不意味着 Dart 在启动时加载所有延迟组件。 +Web 应用可以在需要时通过网络下载延迟组件。 + * Reduce a web app's initial startup time. * Perform A/B testing—trying out alternative implementations of an algorithm, for example. * Load rarely used functionality, such as optional screens and dialogs. + + +`dart` 工具不支持 Web 以外的目标的延迟加载。 +如果你正在构建 Flutter 应用, +请参阅 Flutter 指南中关于[延迟组件][flutter-deferred]的延迟加载实现。 + That doesn't mean Dart loads all the deferred components at start time. The web app can download deferred components via the web when needed. + + +要延迟加载库,首先使用 `deferred as` 导入它。 + The `dart` tool doesn't support deferred loading for targets other than web. If you're building a Flutter app, consult its implementation of deferred loading in the Flutter guide on [deferred components][flutter-deferred]. + + +当你需要该库时,使用库的标识符调用 `loadLibrary()`。 + [flutter-deferred]: {{site.flutter-docs}}/perf/deferred-components To lazily load a library, first import it using `deferred as`. + + +在前面的代码中,`await` 关键字暂停执行,直到库加载完成。 +有关 `async` 和 `await` 的更多信息, +请查看[异步编程](/language/async)。 + ```dart import 'package:greetings/hello.dart' deferred as hello; @@ -130,6 +244,11 @@ import 'package:greetings/hello.dart' deferred as hello; When you need the library, invoke `loadLibrary()` using the library's identifier. + + +你可以在一个库上多次调用 `loadLibrary()` 而不会出现问题。 +该库只会加载一次。 + ```dart Future greet() async { @@ -143,11 +262,29 @@ the `await` keyword pauses execution until the library is loaded. For more information about `async` and `await`, check out [asynchronous programming](/language/async). + + +使用延迟加载时,请记住以下几点: + You can invoke `loadLibrary()` multiple times on a library without problems. The library is loaded only once. + + +* 延迟库的常量在导入文件中不是常量。 + 请记住,这些常量在延迟库加载之前不存在。 +* 你不能在导入文件中使用延迟库中的类型。 + 相反,考虑将接口类型移动到延迟库和导入文件都导入的库中。 +* Dart 会隐式地将 `loadLibrary()` 插入到你使用 + deferred as namespace 定义的命名空间中。 + `loadLibrary()` 函数返回一个 [`Future`](/libraries/dart-async#future)。 + Keep in mind the following when you use deferred loading: + + +### `library` 指令 {:#library-directive} + * A deferred library's constants aren't constants in the importing file. Remember, these constants don't exist until the deferred library is loaded. * You can't use types from a deferred library in the importing file. @@ -158,11 +295,25 @@ Keep in mind the following when you use deferred loading: The `loadLibrary()` function returns a [`Future`](/libraries/dart-async#future). + + +要指定库级别的[文档注释][doc comments]或[元数据注解][metadata annotations], +请将它们附加到文件开头的 `library` 声明上。 + ### The `library` directive {:#library-directive} + + +## 实现库 + To specify library-level [doc comments][] or [metadata annotations][], attach them to a `library` declaration at the start of the file. + + +有关如何实现包的建议,请参阅 +[创建包](/tools/pub/create-packages),包括: + ```dart /// A really great test library. @@ -172,6 +323,13 @@ library; ## Implementing libraries + + +* 如何组织库源代码。 +* 如何使用 `export` 指令。 +* 何时使用 `part` 指令。 +* 如何使用条件导入和导出来实现支持多平台的库。 + See [Create Packages](/tools/pub/create-packages) for advice on how to implement a package, including: diff --git a/src/content/language/loops.md b/src/content/language/loops.md index 55cc14089..3dbb19f1e 100644 --- a/src/content/language/loops.md +++ b/src/content/language/loops.md @@ -1,5 +1,7 @@ --- +# title: Loops title: Loops +# description: Learn how to use loops to control the flow of your Dart code. description: Learn how to use loops to control the flow of your Dart code. prevpage: url: /language/pattern-types @@ -12,19 +14,46 @@ nextpage: This page shows how you can control the flow of your Dart code using loops and supporting statements: + + +本页面展示如何使用循环和辅助语句来控制 Dart 代码的流程: + - `for` loops - `while` and `do while` loops - `break` and `continue` + + +- `for` 循环 +- `while` 和 `do while` 循环 +- `break` 和 `continue` + You can also manipulate control flow in Dart using: + + +你还可以使用以下方式在 Dart 中控制流程: + - [Branching][], like `if` and `switch` - [Exceptions][], like `try`, `catch`, and `throw` + + +- [分支][Branching],如 `if` 和 `switch` +- [异常][Exceptions],如 `try`、`catch` 和 `throw` + ## For loops + + +## For 循环 + You can iterate with the standard `for` loop. For example: + + +你可以使用标准的 `for` 循环进行迭代。例如: + ```dart var message = StringBuffer('Dart is fun'); @@ -36,6 +65,11 @@ for (var i = 0; i < 5; i++) { Closures inside of Dart's `for` loops capture the _value_ of the index. This avoids a common pitfall found in JavaScript. For example, consider: + + +Dart `for` 循环内的闭包会捕获索引的_值_。 +这避免了 JavaScript 中常见的陷阱。例如,考虑: + ```dart var callbacks = []; @@ -48,13 +82,32 @@ for (final c in callbacks) { } ``` + + +输出如预期的那样是 `0` 然后是 `1`。 +相比之下,该示例在 JavaScript 中会打印 `2` 然后是 `2`。 + The output is `0` and then `1`, as expected. In contrast, the example would print `2` and then `2` in JavaScript. + + +有时在遍历 [`Iterable`][] 类型(如 `List` 或 `Set`)时, +你可能不需要知道当前的迭代计数器。 +在这种情况下,使用 `for-in` 循环可以使代码更简洁: + Sometimes you might not need to know the current iteration counter when iterating over an [`Iterable`][] type, like `List` or `Set`. In that case, use the `for-in` loop for cleaner code: + + +在前面的示例循环中,`candidate` 在循环体内定义, +并设置为每次引用 `candidates` 中的一个值。 +`candidate` 是一个局部[变量][variable]。 +在循环体内重新赋值 `candidate` 只会更改该次迭代的局部变量, +不会修改原始的 `candidates` 可迭代对象。 + ```dart for (var candidate in candidates) { @@ -70,9 +123,20 @@ Reassigning `candidate` inside the loop body only changes the local variable for that iteration and doesn't modify the original `candidates` iterable. + + +要处理从可迭代对象获取的值, +你也可以在 `for-in` 循环中使用[模式][pattern]: + To process the values obtained from the iterable, you can also use a [pattern][] in a `for-in` loop: + + +要练习使用 `for-in`,请参阅 +[可迭代集合教程](/libraries/collections/iterables)。 +::: + ```dart for (final Candidate(:name, :yearsExperience) in candidates) { @@ -87,6 +151,10 @@ To practice using `for-in`, follow the Iterable classes also have a [forEach()][] method as another option: + + +可迭代类还有一个 [forEach()][] 方法作为另一种选择: + ```dart var collection = [1, 2, 3]; @@ -97,8 +165,16 @@ collection.forEach(print); // 1 2 3 ## While and do-while + + +## While 和 do-while + A `while` loop evaluates the condition before the loop: + + +`while` 循环在循环之前评估条件: + ```dart while (!isDone()) { @@ -108,6 +184,10 @@ while (!isDone()) { A `do`-`while` loop evaluates the condition *after* the loop: + + +`do`-`while` 循环在循环*之后*评估条件: + ```dart do { @@ -115,11 +195,18 @@ do { } while (!atEndOfPage()); ``` - ## Break and continue + + +## Break 和 continue + Use `break` to stop looping: + + +使用 `break` 停止循环: + ```dart while (true) { @@ -130,6 +217,10 @@ while (true) { Use `continue` to skip to the next loop iteration: + + +使用 `continue` 跳到下一次循环迭代: + ```dart for (int i = 0; i < candidates.length; i++) { @@ -144,6 +235,11 @@ for (int i = 0; i < candidates.length; i++) { If you're using an [`Iterable`][] such as a list or set, how you write the previous example might differ: + + +如果你使用的是 [`Iterable`][](如列表或集合), +编写前面示例的方式可能会有所不同: + ```dart candidates @@ -153,31 +249,69 @@ candidates ## Labels + + +## 标签 + A label is an identifier followed by a colon (`labelName:`) that you can place before a statement to create a _labeled statement_. Loops and switch cases are often used as labeled statements. A labeled statement can be referenced later in a `break` or `continue` statement as follows: + + +标签是一个后跟冒号(`labelName:`)的标识符, +你可以将其放在语句之前以创建_带标签的语句_。 +循环和 switch case 通常用作带标签的语句。 +带标签的语句可以稍后在 `break` 或 `continue` 语句中引用,如下所示: + * `break labelName;` Terminates the execution of the labeled statement. This is useful for breaking out of a specific outer loop when you're within a nested loop. + + +* `break labelName;` + 终止带标签语句的执行。 + 当你在嵌套循环中时,这对于跳出特定的外部循环很有用。 + * `continue labelName;` Skips the rest of the current iteration of the labeled statement loop and continues with the next iteration. + + +* `continue labelName;` + 跳过带标签语句循环当前迭代的剩余部分, + 并继续下一次迭代。 + Labels are used to manage control flow. They are often used with loops and switch cases and allow you to specify which statement to break out of or continue, rather than affecting the innermost loop by default. + + +标签用于管理控制流。它们通常与循环和 switch case 一起使用, +允许你指定要跳出或继续的语句, +而不是默认影响最内层的循环。 + ### Labels in for loop using `break` {:.no_toc} + + +### 在 for 循环中使用 `break` 的标签 {:.no_toc} + The following code demonstrates the usage of a label called `outerLoop` in a `for` loop with a `break` statement: + + +以下代码演示了在带有 `break` 语句的 `for` 循环中 +使用名为 `outerLoop` 的标签: + ```dart outerLoop: @@ -195,6 +329,11 @@ print('outerLoop exited'); In the previous example, when `i == 2` and `j == 2`, the `break outerLoop;` statement stops both inner and outer loops. As a result, the output is: + + +在前面的示例中,当 `i == 2` 且 `j == 2` 时, +`break outerLoop;` 语句会停止内部和外部循环。因此,输出是: + ```plaintext i = 1, j = 1 i = 1, j = 2 @@ -206,9 +345,18 @@ outerLoop exited ### Labels in for loop using `continue` {:.no_toc} + + +### 在 for 循环中使用 `continue` 的标签 {:.no_toc} + The following code demonstrates the use of a label called `outerLoop` in a `for` loop with a `continue` statement: + + +以下代码演示了在带有 `continue` 语句的 `for` 循环中 +使用名为 `outerLoop` 的标签: + ```dart outerLoop: @@ -225,6 +373,12 @@ for (var i = 1; i <= 3; i++) { In the previous example, when `i == 2` and `j == 2`, `continue outerLoop;` skips the rest of the iterations for `i = 2` and moves to `i = 3`. As a result, the output is: + + +在前面的示例中,当 `i == 2` 且 `j == 2` 时, +`continue outerLoop;` 跳过 `i = 2` 的剩余迭代并移动到 `i = 3`。 +因此,输出是: + ```plaintext i = 1, j = 1 i = 1, j = 2 @@ -237,9 +391,18 @@ i = 3, j = 3 ### Labels in while loop using `break` {:.no_toc} + + +### 在 while 循环中使用 `break` 的标签 {:.no_toc} + The following code demonstrates the use of a label called `outerLoop` in a `while` loop with a `break` statement: + + +以下代码演示了在带有 `break` 语句的 `while` 循环中 +使用名为 `outerLoop` 的标签: + ```dart var i = 1; @@ -259,9 +422,18 @@ while (i <= 3) { print('outerLoop exited'); ``` + + +在前面的示例中,当 `i == 2` 且 `j == 2` 时, +程序跳出内部和外部的 `while` 循环。因此,输出是: + In the previous example, the program breaks out of both inner and outer `while` loops when `i == 2` and `j == 2`. As a result, the output is: + + +### 在 while 循环中使用 `continue` 的标签 {:.no_toc} + ```plaintext i = 1, j = 1 i = 1, j = 2 @@ -273,9 +445,19 @@ outerLoop exited ### Labels in while loop using `continue` {:.no_toc} + + +以下代码演示了在带有 `continue` 语句的 `while` 循环中 +使用名为 `outerLoop` 的标签: + The following code demonstrates the use of a label called `outerLoop` in a `while` loop with a `continue` statement: + + +在前面的示例中,`i = 2` 且 `j = 2` 的迭代被跳过, +循环直接移动到 `i = 3`。因此,输出是: + ```dart var i = 1; @@ -295,9 +477,18 @@ while (i <= 3) { } ``` + + +### 在 do-while 循环中使用 `break` 的标签 {:.no_toc} + In the previous example, the iteration for `i = 2` and `j = 2` is skipped and the loop moves directly to `i = 3`. As a result, the output is: + + +以下代码演示了在带有 `break` 语句的 `do while` 循环中 +使用名为 `outerLoop` 的标签: + ```plaintext i = 1, j = 1 i = 1, j = 2 @@ -310,9 +501,18 @@ i = 3, j = 3 ### Labels in do-while loop using `break` {:.no_toc} + + +在前面的示例中,当 `i == 2` 且 `j == 2` 时, +程序跳出内部和外部循环。因此,输出是: + The following code demonstrates the use of a label called `outerLoop` in a `do while` loop with a `break` statement: + + +### 在 do-while 循环中使用 `continue` 的标签 {:.no_toc} + ```dart var i = 1; @@ -330,9 +530,19 @@ do { i++; } while (i <= 3); + + +以下代码演示了在带有 `continue` 语句的 `do while` 循环中 +使用名为 `outerLoop` 的标签: + print('outerLoop exited'); ``` + + +在前面的示例中,循环跳过 `i = 2` 且 `j = 2`, +并直接移动到 `i = 3`。因此,输出是: + In the previous example, the program breaks out of both inner and outer loops when `i == 2` and `j == 2`. As a result, the output is: diff --git a/src/content/language/metadata.md b/src/content/language/metadata.md index ecaae69e2..5ec6d78b9 100644 --- a/src/content/language/metadata.md +++ b/src/content/language/metadata.md @@ -1,5 +1,7 @@ --- +# title: Metadata title: Metadata +# description: Metadata and annotations in Dart. description: Metadata and annotations in Dart. prevpage: url: /language/functions @@ -9,39 +11,87 @@ nextpage: title: Libraries & imports --- - Use metadata to provide additional static information about your code. A metadata annotation begins with the character `@`, followed by either a reference to a compile-time constant (such as `deprecated`) or a call to a constant constructor. + + +使用元数据为代码提供额外的静态信息。 +元数据注解以字符 `@` 开头, +后跟对编译时常量的引用(如 `deprecated`) +或对常量构造函数的调用。 + Metadata can be attached to most Dart program constructs by adding annotations before the construct's declaration or directive. + + +通过在声明或指令之前添加注解, +可以将元数据附加到大多数 Dart 程序结构上。 + ## Built-in annotations + + +## 内置注解 + The following annotations are available to all Dart code: + + +以下注解可用于所有 Dart 代码: + [`@Deprecated`][] : Marks a declaration as deprecated, indicating it should be migrated away from, with a message explaining the replacement and potential removal date. + + +[`@Deprecated`][] +: 将声明标记为已弃用, + 表示应该迁移到其他方案, + 并附带一条消息说明替代方案和可能的移除日期。 + [`@deprecated`][] : Marks a declaration as deprecated until an unspecified future release. Prefer using `@Deprecated` and [providing a deprecation message][]. + + +[`@deprecated`][] +: 将声明标记为已弃用,直到未来某个未指定的版本。 + 建议使用 `@Deprecated` 并[提供弃用消息][providing a deprecation message]。 + [`@override`][] : Marks an instance member as an override or implementation of a member with the same name from a parent class or interface. For examples of using `@override`, check out [Extend a class][]. + + +[`@override`][] +: 将实例成员标记为对父类或接口中同名成员的重写或实现。 + 有关使用 `@override` 的示例,请查看[扩展一个类][Extend a class]。 + [`@pragma`][] : Provides specific instructions or hints about a declaration to Dart tools, such as the compiler or analyzer. + + +[`@pragma`][] +: 向 Dart 工具(如编译器或分析器)提供 + 关于声明的特定指令或提示。 + Here's an example of using the `@Deprecated` annotation: + + +下面是使用 `@Deprecated` 注解的示例: + ```dart highlightLines=3 class Television { @@ -51,7 +101,7 @@ class Television { turnOn(); } - /// Turns the TV's power on. +/// Turns the TV's power on. void turnOn() { // ··· } @@ -59,10 +109,20 @@ class Television { } ``` + + +[Dart 分析器][Dart analyzer]会在需要 `@override` 注解时 +以及使用带有 `@deprecated` 或 `@Deprecated` 注解的成员时 +提供诊断反馈。 + The [Dart analyzer][] provides feedback as diagnostics if the `@override` annotation is needed and when using members annotated with `@deprecated` or `@Deprecated`. + + +## 分析器支持的注解 + [`@Deprecated`]: {{site.dart-api}}/dart-core/Deprecated-class.html [`@deprecated`]: {{site.dart-api}}/dart-core/deprecated-constant.html [`@override`]: {{site.dart-api}}/dart-core/override-constant.html @@ -73,27 +133,60 @@ members annotated with `@deprecated` or `@Deprecated`. ## Analyzer-supported annotations + + +除了为[内置注解][built-in annotations]提供支持和分析外, +[Dart 分析器][Dart analyzer]还为来自 [`package:meta`][] 的 +各种注解提供额外的支持和诊断。 +该包提供的一些常用注解包括: + Beyond providing support and analysis for the [built-in annotations][], the [Dart analyzer][] provides additional support and diagnostics for a variety of annotations from [`package:meta`][]. Some commonly used annotations the package provides include: + + +[`@visibleForTesting`][] +: 将包的成员标记为仅为公开状态, + 以便可以从包的测试中访问该成员。 + 分析器会在自动完成建议中隐藏该成员, + 并在其他包使用时发出警告。 + [`@visibleForTesting`][] : Marks a member of a package as only public so that the member can be accessed from the package's tests. The analyzer hides the member from autocompletion suggestions and warns if it's used from another package. + + +[`@awaitNotRequired`][] +: 将具有 `Future` 类型的变量或返回 `Future` 的函数 + 标记为不需要调用者 await 该 `Future`。 + 这会阻止分析器因 [`discarded_futures`][] 或 [`unawaited_futures`][] 规则 + 而警告未 await `Future` 的调用者。 + [`@awaitNotRequired`][] : Marks variables that have a `Future` type or functions that return a `Future` as not requiring the caller to await the `Future`. This stops the analyzer from warning callers that don't await the `Future` due to the [`discarded_futures`][] or [`unawaited_futures`][] lints. + + +要了解更多关于这些注解和该包提供的其他注解、 +它们的含义、它们启用的功能以及如何使用它们, +请查看 [`package:meta/meta.dart` API 文档][meta-api]。 + To learn more about these and the other annotations the package provides, what they indicate, what functionality they enable, and how to use them, check out the [`package:meta/meta.dart` API docs][meta-api]. + + +## 自定义注解 + [built-in annotations]: #built-in-annotations [Dart analyzer]: /tools/analysis [`@visibleForTesting`]: {{site.pub-api}}/meta/latest/meta/visibleForTesting-constant.html @@ -104,21 +197,39 @@ check out the [`package:meta/meta.dart` API docs][meta-api]. ## Custom annotations + + +你可以定义自己的元数据注解。下面是一个定义接受两个参数的 +`@Todo` 注解的示例: + You can define your own metadata annotations. Here's an example of defining a `@Todo` annotation that takes two arguments: + + +下面是使用 `@Todo` 注解的示例: + ```dart class Todo { final String who; final String what; - const Todo(this.who, this.what); +const Todo(this.who, this.what); } ``` + + +### 指定支持的目标 {:.no_toc} + And here's an example of using that `@Todo` annotation: + + +要指示应该使用你的注解标注的语言结构类型, +请使用 [`package:meta`][] 中的 [`@Target`][] 注解。 + ```dart highlightLines=1 @Todo('Dash', 'Implement this function') @@ -129,10 +240,21 @@ void doSomething() { ### Specifying supported targets {:.no_toc} + + +例如,如果你希望前面的 `@Todo` 注解 +只能用于函数和方法, +你可以添加以下注解: + To indicate the type of language constructs that should be annotated with your annotation, use the [`@Target`][] annotation from [`package:meta`][]. + + +使用此配置,如果 `Todo` 被用作顶层函数或方法以外的 +任何声明的注解,分析器将发出警告。 + For example, if you wanted the earlier `@Todo` annotation to only be allowed on functions and methods, you'd add the following annotation: diff --git a/src/content/language/methods.md b/src/content/language/methods.md index 570274f66..9383354a7 100644 --- a/src/content/language/methods.md +++ b/src/content/language/methods.md @@ -1,5 +1,7 @@ --- +# title: Methods title: Methods +# description: Learn about methods in Dart. description: Learn about methods in Dart. prevpage: url: /language/constructors @@ -13,12 +15,25 @@ nextpage: Methods are functions that provide behavior for an object. + + +方法是为对象提供行为的函数。 + ## Instance methods + + +## 实例方法 + Instance methods on objects can access instance variables and `this`. The `distanceTo()` method in the following sample is an example of an instance method: + + +对象的实例方法可以访问实例变量和 `this`。 +下面示例中的 `distanceTo()` 方法就是一个实例方法的例子: + ```dart import 'dart:math'; @@ -27,24 +42,59 @@ class Point { final double x; final double y; - // Sets the x and y instance variables + + +## 运算符 + +// Sets the x and y instance variables // before the constructor body runs. Point(this.x, this.y); - double distanceTo(Point other) { + + +大多数运算符是具有特殊名称的实例方法。 +Dart 允许你使用以下名称定义运算符: + +double distanceTo(Point other) { var dx = x - other.x; var dy = y - other.y; return sqrt(dx * dx + dy * dy); } + + +你可能已经注意到,一些[运算符][operators],如 `!=`, +不在名称列表中。这些运算符不是实例方法。 +它们的行为是 Dart 内置的。 +::: + } ``` + + +要声明一个运算符,请使用内置标识符 `operator`, +然后是你要定义的运算符。 +下面的示例定义了向量加法(`+`)、减法(`-`) +和相等(`==`)运算符: + ## Operators + + +## Getter 和 Setter + Most operators are instance methods with special names. Dart allows you to define operators with the following names: + + +Getter 和 setter 是提供对象属性读写访问的特殊方法。 +回想一下,每个实例变量都有一个隐式的 getter, +如果合适的话还有一个 setter。 +你可以使用 `get` 和 `set` 关键字来实现 getter 和 setter, +从而创建额外的属性: + | | | | | | | |-------|------|------|------|-------|------| | `<` | `>` | `<=` | `>=` | `==` | `~` | @@ -54,6 +104,11 @@ Dart allows you to define operators with the following names: {:.table} + + +使用 getter 和 setter,你可以从实例变量开始, +之后用方法包装它们,而无需更改客户端代码。 + :::note You may have noticed that some [operators][], like `!=`, aren't in the list of names. These operators aren't instance methods. @@ -71,21 +126,43 @@ To declare an operator, use the built-in identifier The following example defines vector addition (`+`), subtraction (`-`), and equality (`==`): + + +无论是否显式定义了 getter, +像自增(`++`)这样的运算符都会按预期方式工作。 +为了避免任何意外的副作用, +运算符只调用一次 getter,并将其值保存在临时变量中。 +::: + ```dart class Vector { final int x, y; - Vector(this.x, this.y); +Vector(this.x, this.y); + + - Vector operator +(Vector v) => Vector(x + v.x, y + v.y); +## 抽象方法 + +Vector operator +(Vector v) => Vector(x + v.x, y + v.y); Vector operator -(Vector v) => Vector(x - v.x, y - v.y); - @override + + +实例方法、getter 和 setter 方法可以是抽象的, +定义一个接口但将其实现留给其他类。 +抽象方法只能存在于[抽象类][abstract classes]或 [mixin][mixins] 中。 + +@override bool operator ==(Object other) => other is Vector && x == other.x && y == other.y; - @override + + +要使方法成为抽象方法,请使用分号(`;`)代替方法体: + +@override int get hashCode => Object.hash(x, y); } @@ -93,12 +170,11 @@ void main() { final v = Vector(2, 3); final w = Vector(2, 2); - assert(v + w == Vector(4, 5)); +assert(v + w == Vector(4, 5)); assert(v - w == Vector(0, 1)); } ``` - ## Getters and setters Getters and setters are special methods that provide read and write @@ -114,9 +190,9 @@ additional properties by implementing getters and setters, using the class Rectangle { double left, top, width, height; - Rectangle(this.left, this.top, this.width, this.height); +Rectangle(this.left, this.top, this.width, this.height); - // Define two calculated properties: right and bottom. +// Define two calculated properties: right and bottom. double get right => left + width; set right(double value) => left = value - width; double get bottom => top + height; @@ -154,7 +230,7 @@ To make a method abstract, use a semicolon (`;`) instead of a method body: abstract class Doer { // Define instance variables and methods... - void doSomething(); // Define an abstract method. +void doSomething(); // Define an abstract method. } class EffectiveDoer extends Doer { diff --git a/src/content/language/mixins.md b/src/content/language/mixins.md index e9cf526f4..ffeea37e4 100644 --- a/src/content/language/mixins.md +++ b/src/content/language/mixins.md @@ -1,5 +1,7 @@ --- +# title: Mixins title: Mixins +# description: Learn how to add to features to a class in Dart. description: Learn how to add to features to a class in Dart. prevpage: url: /language/extend @@ -12,12 +14,22 @@ nextpage: Mixins are a way of defining code that can be reused in multiple class hierarchies. -They are intended to provide member implementations en masse. +They are intended to provide member implementations en masse. + + + +Mixin 是一种在多个类层次结构中重用代码的方式。 +它们旨在批量提供成员实现。 To use a mixin, use the `with` keyword followed by one or more mixin names. The following example shows two classes that use (or, are subclasses of) mixins: + + +要使用 mixin,请使用 `with` 关键字后跟一个或多个 mixin 名称。 +下面的示例展示了两个使用(或者说是子类化)mixin 的类: + ```dart class Musician extends Performer [!with Musical!] { @@ -32,15 +44,34 @@ class Maestro extends Person [!with Musical, Aggressive, Demented!] { } ``` + + +要定义 mixin,请使用 `mixin` 声明。 +在需要同时定义 mixin _和_ 类的罕见情况下, +你可以使用 [`mixin class` 声明](#class-mixin-or-mixin-class)。 + To define a mixin, use the `mixin` declaration. In the rare case where you need to define both a mixin _and_ a class, you can use the [`mixin class` declaration](#class-mixin-or-mixin-class). + + +Mixin 和 mixin 类不能有 `extends` 子句, +并且不能声明任何生成式构造函数。 + Mixins and mixin classes cannot have an `extends` clause, and must not declare any generative constructors. + + +例如: + For example: + + +## 指定 mixin 可以调用自身的成员 + ```dart mixin Musical { @@ -48,7 +79,7 @@ mixin Musical { bool canCompose = false; bool canConduct = false; - void entertainMe() { +void entertainMe() { if (canPlayPiano) { print('Playing piano'); } else if (canConduct) { @@ -60,25 +91,54 @@ mixin Musical { } ``` + + +有时 mixin 依赖于能够调用方法或访问字段, +但不能自己定义这些成员(因为 mixin 不能使用构造函数参数 +来实例化自己的字段)。 + ## Specify members a mixin can call on itself + + +以下部分介绍了确保 mixin 的任何子类定义 mixin 行为所依赖的 +任何成员的不同策略。 + Sometimes a mixin depends on being able to invoke a method or access fields, but can't define those members itself (because mixins can't use constructor parameters to instantiate their own fields). + + +### 在 mixin 中定义抽象成员 + The following sections cover different strategies for ensuring any subclass -of a mixin defines any members the mixin's behavior depends on. +of a mixin defines any members the mixin's behavior depends on. + + + +在 mixin 中声明抽象方法会强制任何使用该 mixin 的类型 +定义其行为所依赖的抽象方法。 ### Define abstract members in the mixin + + +#### 访问 mixin 子类中的状态 + Declaring an abstract method in a mixin forces any type that uses -the mixin to define the abstract method upon which its behavior depends. +the mixin to define the abstract method upon which its behavior depends. + + + +声明抽象成员还允许你通过调用在 mixin 上定义为抽象的 getter +来访问 mixin 子类上的状态: ```dart mixin Musician { void playInstrument(String instrumentName); // Abstract method. - void playPiano() { +void playPiano() { playInstrument('Piano'); } void playFlute() { @@ -86,46 +146,101 @@ mixin Musician { } } -class Virtuoso with Musician { - @override + +### 实现接口 + +class Virtuoso with Musician { + + + +与将 mixin 声明为抽象类似,在 mixin 上放置 `implements` 子句 +但不实际实现接口,也将确保为 mixin 定义任何成员依赖项。 + +@override void playInstrument(String instrumentName) { // Subclass must define. print('Plays the $instrumentName beautifully'); } } ``` + + +### 使用 `on` 子句声明超类 + #### Access state in the mixin's subclass + + +`on` 子句用于定义 `super` 调用所针对的类型。 +因此,只有在需要在 mixin 中使用 `super` 调用时才应该使用它。 + Declaring abstract members also allows you to access state on the subclass of a mixin, by calling getters which are defined as abstract on the mixin: + + +`on` 子句强制任何使用 mixin 的类也必须是 `on` 子句中类型的子类。 +如果 mixin 依赖于超类中的成员, +这可以确保在使用 mixin 的地方这些成员是可用的: + ```dart /// Can be applied to any type with a [name] property and provides an /// implementation of [hashCode] and operator `==` in terms of it. mixin NameIdentity { String get name; - @override +@override int get hashCode => name.hashCode; - @override + + +在这个示例中,只有扩展或实现 `Musician` 类的类 +才能使用 `MusicalPerformer` mixin。 +因为 `SingerDancer` 扩展了 `Musician`, +所以 `SingerDancer` 可以混入 `MusicalPerformer`。 + +@override bool operator ==(other) => other is NameIdentity && name == other.name; } + + +## `class`、`mixin` 还是 `mixin class`? + class Person with NameIdentity { final String name; - Person(this.name); + + +`mixin class` 声明需要至少 3.0 的[语言版本][language version]。 +::: + +Person(this.name); } ``` + + +`mixin` 声明定义了一个 mixin。`class` 声明定义了一个[类][class]。 +`mixin class` 声明定义了一个既可以用作普通类又可以用作 mixin 的类, +具有相同的名称和相同的类型。 + ### Implement an interface + + +适用于类或 mixin 的任何限制也适用于 mixin 类: + Similar to declaring the mixin abstract, putting an `implements` clause on the mixin while not actually implementing the interface will also ensure any member dependencies are defined for the mixin. + + +- Mixin 不能有 `extends` 或 `with` 子句,因此 `mixin class` 也不能有。 +- 类不能有 `on` 子句,因此 `mixin class` 也不能有。 + ```dart abstract interface class Tuner { void tuneInstrument(); @@ -135,13 +250,13 @@ mixin Guitarist implements Tuner { void playSong() { tuneInstrument(); - print('Strums guitar majestically.'); +print('Strums guitar majestically.'); } } class PunkRocker with Guitarist { - @override +@override void tuneInstrument() { print("Don't bother, being out of tune is punk rock."); } @@ -151,7 +266,7 @@ class PunkRocker with Guitarist { ### Use the `on` clause to declare a superclass The `on` clause exists to define the type that `super` calls are resolved against. -So, you should only use it if you need to have a `super` call inside a mixin. +So, you should only use it if you need to have a `super` call inside a mixin. The `on` clause forces any class that uses a mixin to also be a subclass of the type in the `on` clause. diff --git a/src/content/language/modifier-reference.md b/src/content/language/modifier-reference.md index 208c25579..01e423ce1 100644 --- a/src/content/language/modifier-reference.md +++ b/src/content/language/modifier-reference.md @@ -1,5 +1,8 @@ --- +# title: Class modifiers reference title: Class modifiers reference +# description: >- +# The allowed and disallowed combinations of class modifiers. description: >- The allowed and disallowed combinations of class modifiers. prevpage: @@ -13,10 +16,22 @@ nextpage: This page contains reference information for [class modifiers](/language/class-modifiers). + + +本页面包含[类修饰符](/language/class-modifiers)的参考信息。 + ## Valid combinations + + +## 有效组合 + The valid combinations of class modifiers and their resulting capabilities are: + + +类修饰符的有效组合及其产生的功能如下: + | Declaration | [Construct][]? | [Extend][]? | [Implement][]? | [Mix in][]? | [Exhaustive][]? | |-----------------------------|----------------|-------------|----------------|-------------|-----------------| | `class` | **Yes** | **Yes** | **Yes** | No | No | @@ -37,6 +52,10 @@ The valid combinations of class modifiers and their resulting capabilities are: {: .table .table-striped .nowrap} + + +## 无效组合 + [Construct]: /language/classes#using-constructors [Extend]: /language/extend [Implement]: /language/classes#implicit-interfaces @@ -45,8 +64,24 @@ The valid combinations of class modifiers and their resulting capabilities are: ## Invalid combinations + + +某些修饰符[组合][combinations]是不允许的: + Certain [combinations][] of modifiers aren't allowed: + + +| 组合 | 原因 | +|-----------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------| +| `base`、`interface` 和 `final` | 都控制相同的两种功能(`extend` 和 `implement`),因此是互斥的。 | +| `sealed` 和 `abstract` | 两者都不能被构造,因此放在一起是多余的。 | +| `sealed` 与 `base`、`interface` 或 `final` | `sealed` 类型已经不能从另一个库中被混入、扩展或实现,因此与列出的修饰符组合是多余的。 | +| `mixin` 和 `abstract` | 两者都不能被构造,因此放在一起是多余的。 | +| `mixin` 与 `interface`、`final` 或 `sealed` | `mixin` 或 `mixin class` 声明旨在被混入,而列出的修饰符会阻止这一点。 | +| `enum` 和任何修饰符 | `enum` 声明不能被扩展、实现或混入,且总是可以被实例化,因此没有修饰符适用于 `enum` 声明。 | +| `extension type` 和任何修饰符 | `extension type` 声明不能被扩展或混入,且只能被其他 `extension type` 声明实现。 | + | Combination | Reasoning | |-----------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------| | `base`, `interface`, and `final` | All control the same two capabilities (`extend` and `implement`), so are mutually exclusive. | diff --git a/src/content/language/typedefs.md b/src/content/language/typedefs.md index 5595c9beb..9d9ea029c 100644 --- a/src/content/language/typedefs.md +++ b/src/content/language/typedefs.md @@ -1,5 +1,7 @@ --- +# title: Typedefs title: Typedefs +# description: Learn about type aliases in Dart. description: Learn about type aliases in Dart. showToc: false prevpage: @@ -17,6 +19,13 @@ it's declared with the keyword `typedef`—is a concise way to refer to a type. Here's an example of declaring and using a type alias named `IntList`: + + +类型别名——通常被称为 _typedef_, +因为它是用关键字 `typedef` 声明的——是 +一种简洁地引用类型的方式。 +下面是一个声明和使用名为 `IntList` 的类型别名的示例: + ```dart typedef IntList = List; @@ -25,6 +34,10 @@ IntList il = [1, 2, 3]; A type alias can have type parameters: + + +类型别名可以有类型参数: + ```dart typedef ListMapper = Map>; @@ -41,12 +54,24 @@ We recommend using [inline function types][] instead of typedefs for functions, in most situations. However, function typedefs can still be useful: + + +在 2.13 之前,typedef 仅限于函数类型。 +使用新的 typedef 需要[语言版本][language version]至少为 2.13。 +::: + ```dart typedef Compare = int Function(T a, T b); int sort(int a, int b) => a - b; + + +在大多数情况下,我们建议使用[内联函数类型][inline function types] +而不是函数的 typedef。 +但是,函数 typedef 仍然很有用: + void main() { assert(sort is Compare); // True! }