dart 语法

ads

本篇简要的说明一下Dart在编写过程中官方推荐的一些实践,有以下几个方面:

  1. 代码风格
  2. 文档
  3. 应用示例
  4. API设计

代码风格

在 Dart 中标识符有三种类型。

  • UpperCamelCase 每个单词的首字母都大写,包含第一个单词。
  • lowerCamelCase 除了第一个字母始终是小写(即使是缩略词),每个单词的首字母都大写。
  • lowercase_with_underscores 只是用小写字母单词,即使是缩略词,并且单词之间使用 _ 连接。

SliderMenuclearItemsangular_components

UpperCamelCase 风格命名类型

Classes(类名)、 enums(枚举类型)、 typedefs(类型定义)、以及 type parameters(类型参数)应该把每个单词的首字母都大写(包含第一个单词),不使用分隔符。

class SliderMenu { ... }
class HttpRequest { ... }
typedef Predicate<T> = bool Function(T value);

使用 UpperCamelCase 风格类型作为扩展名

与类型命名一样,扩展 的名称也应大写每个单词的首字母(包括第一个单词),并且不使用分隔符。

extension MyFancyList<T> on List<T> { ... }
extension SmartIterable<T> on Iterable<T> { ... }

在库,package,文件夹,源文件 中使用 lowercase_with_underscores 方式命名

library peg_parser.source_scanner;

import 'file_system.dart';
import 'slider_menu.dart';

用 lowercase_with_underscores 风格命名库和源文件名

import 'dart:math' as math;
import 'package:angular_components/angular_components.dart' as angular_components;
import 'package:js/js.dart' as js;

使用 lowerCamelCase 风格来命名其他的标识符

var count = 3;

HttpRequest httpRequest;

void align(bool clearItems) {
  // ...
}

使用 lowerCamelCase 来命名常量

const pi = 3.14;
const defaultTimeout = 1000;
final urlScheme = RegExp('^([a-z]+):');

class Dice {
  static final numberGenerator = Random();
}

使用 _ 替代用不到的回调值

futureOfVoid.then((_) {
  print('Operation complete.');
});

把 “dart:” 导入语句放到其他导入语句之前

import 'dart:async';
import 'dart:html';

import 'package:bar/bar.dart';
import 'package:foo/foo.dart';

要 把 “package:” 导入语句放到项目相关导入语句之前

import 'package:bar/bar.dart';
import 'package:foo/foo.dart';

import 'util.dart';

把导出(export)语句作为一个单独的部分放到所有导入语句之后

import 'src/error.dart';
import 'src/foo_bar.dart';

export 'src/error.dart';

按照字母顺序来排序每个部分中的语句

import 'package:bar/bar.dart';
import 'package:foo/foo.dart';

import 'foo.dart';
import 'foo/foo.dart';

文档

使用 /// 文档注释来注释成员和类型

/// The number of characters in this chunk when unsplit.
int get length => ...

要在文档注释开头有一个单句总结

/// Deletes the file at [path] from the file system.
void delete(String path) {
  ...
}

让文档注释的第一句从段落中分开

在第一句之后添加一个空行,将其拆分为自己的段落。如果不止一个解释句子有用,请将其余部分放在后面的段落中。

这有助于您编写一个紧凑的第一句话来总结文档。此外,像Dartdoc这样的工具使用第一段作为类和类成员列表等地方的简短摘要。

/// Deletes the file at [path].
///
/// Throws an [IOError] if the file could not be found. Throws a

/// [PermissionError] if the file is present but could not be deleted.
void delete(String path) {
  ...
}

避免 与周围上下文冗余。

class RadioButtonWidget extends Widget {
  /// Sets the tooltip to [lines], which should have been word wrapped using
  /// the current font.
  void tooltip(List<String> lines) {
    ...
  }
}

而不是:

class RadioButtonWidget extends Widget {
  /// Sets the tooltip for this radio button widget to the list of strings in
  /// [lines].
  void tooltip(List<String> lines) {
    ...
  }
}

用第三人称来开始函数或者方法的文档注释

/// Returns `true` if every element satisfies the [predicate].
bool all(bool predicate(T element)) => ...

/// Starts the stopwatch if not already running.
void start() {
  ...
}

使用名词短语来为非布尔值变量或属性注释。

/// The current day of the week, where `0` is Sunday.
int weekday;

/// The number of checked buttons on the page.
int get checkedCount => ...

使用名词短语来开始库和类型注释

在程序中,类的注释通常是最重要的文档。类的注释描述了类型的不变性、介绍其使用的术语、提供类成员使用的上下文信息。为类提供一些注释可以让其他类成员的注释更易于理解和编写。

/// A chunk of non-breaking output text terminated by a hard or soft newline.
///
/// ...

class Chunk { ... }

在文档注释中添加示例代码。

/// Returns the lesser of two numbers.
///
/// ```dart

/// min(5, 3) == 3
/// ```
num min(num a, num b) => ...

人类非常擅长从示例中抽象出实质内容,所以即使提供一行最简单的示例代码都可以让 API 更易于理解。

使用方括号在文档注释中引用作用域内的标识符

如果给变量,方法,或类型等名称加上方括号,则 dartdoc 会查找名称并链接到相关的 API 文档。括号是可选的,但是当你在引用一个方法或者构造函数时,可以让注释更清晰。

/// Throws a [StateError] if ...
/// similar to [anotherMethod()], but ...

使用散文的方式来描述参数、返回值以及异常信息

Dart不像其他语言,它推荐用一段话描述参数的内容:

/// Defines a flag.
///
/// Throws an [ArgumentError] if there is already an option named [name] or

/// there is already an option using abbreviation [abbr]. Returns the new flag.
Flag addFlag(String name, String abbr) => ...

而不是:

/// Defines a flag with the given name and abbreviation.
///
/// @param name The name of the flag.

/// @param abbr The abbreviation for the flag.
/// @returns The new flag.
/// @throws ArgumentError If there is already an option with
///     the given name or abbreviation.
Flag addFlag(String name, String abbr) => ...

用法示例

在 part of 中使用字符串

很多 Dart 开发者会避免直接使用 part 。他们发现当库仅有一个文件的时候很容易读懂代码。如果你确实要使用 part 将库的一部分拆分为另一个文件,则 Dart 要求另一个文件指示它所属库的路径。由于遗留原因, Dart 允许 part of 指令使用它所属的库的名称。这使得工具很难直接查找到这个文件对应主库文件,使得库和文件之间的关系模糊不清。

推荐的现代语法是使用 URI 字符串直接指向库文件。首选的现代语法是使用直接指向库文件的URI字符串,URI 的使用和其他指令中一样。如果你有一些库,my_library.dart,其中包含:

library my_library;

part 'some/other/file.dart';

从库中拆分的文件应该如下所示:

part of '../../my_library.dart';

而不是:

part of my_library;

不要 导入 package 中 src 目录下的库

lib 下的 src 目录 被指定 为 package 自己实现的私有库。基于包维护者对版本的考虑,package 使用了这种约定。在不破坏 package 的情况下,维护者可以自由地对 src 目录下的代码进行修改。

这意味着,你如果导入了其中的私有库,按理论来讲,一个不破坏 package 的次版本就会影响到你的代码。

推荐使用相对路径引入

比如,下面是你的 package 目录结构:

my_package
└─ lib
   ├─ src
   │  └─ stuff.dart
   │  └─ utils.dart
   └─ api.dart
   test
   │─ api_test.dart
   └─ test_utils.dart

Here is how the various libraries should import each other:

如果 api.dart 想导入 utils.dart ,应该这样使用:

import 'src/stuff.dart';
import 'src/utils.dart';

// lib/src/utils.dart:
import '../api.dart';
import 'stuff.dart';

// test/api_test.dart:
import 'package:my_package/api.dart'// Don't reach into 'lib'.
import 'test_utils.dart'// Relative within 'test' is fine.

使用相邻字符串的方式连接字面量字符串

如果你有两个字面量字符串(不是变量,是放在引号中的字符串),你不需要使用 + 来连接它们。应该像 C 和 C++ 一样,只需要将它们挨着在一起就可以了。这种方式非常适合不能放到一行的长字符串的创建。

raiseAlarm('ERROR: Parts of the spaceship are on fire. Other '
    'parts are overrun by martians. Unclear which are which.');

使用插值的形式来组合字符串和值

如果你之前使用过其他语言,你一定习惯使用大量 + 将字面量字符串以及字符串变量链接构建字符串。这种方式在 Dart 中同样有效,但是通常情况下使用插值会更清晰简短:

'Hello, $name! You are ${year - birth} years old.';

避免 在字符串插值中使用不必要的大括号

如果要插入是一个简单的标识符,并且后面没有紧跟随在其他字母文本,则应省略 {} 。

var greeting = 'Hi, $name! I love your ${decade}s costume.';

要 尽可能的使用集合字面量

Dart 有三种核心集合类型。List、Map 和 Set,这些类和大多数类一样,都有未命名的构造函数,但由于这些集合使用频率很高,Dart 有更好的内置语法来创建它们:

var points = <Point>[];
var addresses = <String, Address>{};
var counts = <int>{};

而不是:

var addresses = Map<String, Address>();
var counts = Set<int>();

不要 使用 .length 来判断一个集合是否为空

Iterable 合约并不要求集合知道其长度,也没要求在遍历的时候其长度不能改变。通过调用 .length 来判断集合是否包含内容是非常低效的。

相反,Dart 提供了更加高效率和易用的 getter 函数:.isEmpty 和.isNotEmpty。使用这些函数并不需要对结果再次取非。

if (lunchBox.isEmpty) return 'so hungry...';
if (words.isNotEmpty) return words.join(' ');

避免 在 Iterable.forEach() 中使用字面量函数

forEach() 函数在 JavaScript 中被广泛使用,这因为内置的 for-in 循环通常不能达到你想要的效果。在Dart中,如果要对序列进行迭代,惯用的方式是使用循环。

for (final person in people) {
  ...
}

而不是

people.forEach((person) {
  ...
});

API 设计

要 使用一致的术语

在你的代码中,同样的东西要使用同样的名字。如果之前已经存在的 API 之外命名,并且用户已经熟知,那么请继续使用这个命名。

pageCount         // A field.
updatePageCount() // Consistent with pageCount.
toSomething()     // Consistent with Iterable's toList().
asSomething()     // Consistent with List's asMap().
Point             // A familiar concept.

总的目的是充分利用用户已经知道的内容。这里包括他们所了解的问题领域,所熟悉的核心库,以及你自己 API 那部分。基于以上这些内容,他们在使用之前,不需要学习大量的新知识。

避免 缩写

pageCount
buildRectangles
IOStream
HttpRequest

推荐 把最具描述性的名词放到最后

pageCount             // A count (of pages).
ConversionSink        // A sink for doing conversions.
ChunkedConversionSink // A ConversionSink that's chunked.
CssFontFaceRule       // A rule for font faces in CSS.

考虑 尽量让代码看起来像普通的句子

// "If errors is empty..."
if (errors.isEmpty) ...

// "Hey, subscription, cancel!"
subscription.cancel();

// "Get the monsters where the monster has claws."
monsters.where((monster) => monster.hasClaws);

推荐 使用名词短语来命名不是布尔类型的变量和属性

读者关注属性是什么。如果用户更关心如何确定一个属性,则很可能应该是一个使用动词短语命名函数。

list.length
context.lineWidth
quest.rampagingSwampBeast

暂时就写这么多,具体可以到官网上看呢。


最后编辑于:2024/1/10 拔丝英语网

admin-avatar

英语作文代写、国外视频下载

高质量学习资料分享

admin@buzzrecipe.com