Dart fundamentals
掌握 Dart 语言的基础要素(变量、操作符、控制流、函数、导库),用于编写符合规范的 Dart 代码。From its SKILL.md
npx -y skills add Python51888/StudyDart-Skills --skill dart-fundamentalsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
- runs commandsInstructs the agent to run 1 command, including `dart analyze`.
SKILL.md
10.1 KB, ~3.3k tokens by cl100k_base, as published. Nobody here has run it
掌握 Dart 语言基础
Contents
变量与类型推断
声明方式
var name = 'Dart'; // 类型推断为 String
final age = 10; // 不可重新赋值,推断为 int
const pi = 3.14; // 编译时常量,推断为 double
String greeting = 'Hi'; // 显式类型声明
int? nullableValue; // 可空类型,默认为 null
late String lazyInit; // 延迟初始化
选择指南
| 场景 | 推荐 |
|---|---|
| 局部变量,值会变 | var |
| 局部变量,值不变 | final |
| 编译时常量 | const |
| API 边界、字段 | 显式类型 |
| 可能为 null | 显式可空类型 ? |
final 与 const 的区别
final now = DateTime.now(); // OK,运行时确定
const time = DateTime.now(); // 错误!编译时常量不能是运行时值
const list = [1, 2, 3]; // 深度不可变
final mutList = [1, 2, 3]; // 不可重新赋值但内容可变
mutList.add(4); // OK
操作符
算术与比较
// 算术
a + b a - b a * b a / b a ~/ b a % b
// 比较
a == b a != b a > b a < b a >= b a <= b
// 类型检查
a is String a is! String a as String
逻辑与空安全操作符
// 逻辑操作符
!a a && b a || b
// 空安全操作符
a ?? b // 如果 a 为 null 则取 b
a?.b // 安全访问:a 为 null 时短路返回 null
a ??= b // 如果 a 为 null 则赋值 b
a! // 断言非 null(运行时检查)
级联操作符
// 级联 (..) 对同一对象执行多个操作
var buffer = StringBuffer()
..write('Hello')
..write(' ')
..writeAll(['Dart', '!']);
// 空安全级联 (?..)
StringBuffer? buf;
buf?..write('safe');
集合操作符
// Spread (...)
var list = [1, 2, 3];
var combined = [0, ...list, 4]; // [0, 1, 2, 3, 4]
// 空安全 spread (...?)
List<int>? nullableList;
var safe = [0, ...?nullableList]; // [0]
// Collection if / for
var nav = ['Home', if (isAdmin) 'Admin', for (var i in items) '#$i'];
控制流
分支
// if-else
if (isRaining) {
bringUmbrella();
} else if (isSunny) {
wearSunglasses();
} else {
stayHome();
}
// switch 表达式 (Dart 3+)
var status = switch (score) {
>= 90 => '优秀',
>= 60 => '及格',
_ => '不及格',
};
// switch 语句 + 模式匹配
switch (pair) {
case (int x, int y):
print('坐标: ($x, $y)');
case (String name, _):
print('文本: $name');
}
循环
// for
for (var i = 0; i < 5; i++) { ... }
// for-in
for (final item in items) { ... }
// while / do-while
while (condition) { ... }
do { ... } while (condition);
// 可迭代方法链
items.where((e) => e > 0).map((e) => e * 2).forEach(print);
函数
函数定义
// 基本函数
int add(int a, int b) => a + b;
// 可选位置参数
String greet(String name, [String? title]) {
return '${title ?? ''} $name';
}
// 可选命名参数(推荐)
String format({
required String text,
bool bold = false,
Color? color,
}) {
// ...
}
// 匿名函数(lambda)
var list = ['a', 'bb', 'ccc'];
list.where((e) => e.length > 1);
参数最佳实践
- 必要的参数使用
required命名参数(Dart 3+ 不再推荐大量位置参数) - 可选参数提供合理的默认值
- 函数体短于一行时使用
=>箭头语法
函数作为一等公民
void Function(int) callback = (value) => print(value);
void execute(void Function(int) fn, int data) {
fn(data);
}
// 级联传递
[1, 2, 3].map((e) => e * 2).where((e) => e > 2).toList();
库与导入
创建库
// lib/my_library.dart
library my_library;
// 导出公开 API
export 'src/internal.dart' show PublicClass;
导入方式
// 核心库
import 'dart:math';
// Package 库
import 'package:http/http.dart' as http;
// 相对路径导入
import '../utils/helpers.dart';
// show / hide(控制导入范围)
import 'package:lib/lib.dart' show VisibleFunction;
import 'package:lib/lib.dart' hide InternalClass;
// 延迟导入(懒加载)
import 'package:heavy_lib/heavy_lib.dart' deferred as heavy;
// 使用时:
await heavy.loadLibrary();
heavy.HeavyClass().doWork();
库可见性
- 以下划线
_开头的标识符是库私有的 - 每个 Dart 文件是一个独立的库
part和part of用于将一个库拆分到多个文件中
// src/base.dart
part 'internal.dart';
class PublicClass {} // 外部可见
class _PrivateClass {} // 仅本库可见
// src/internal.dart
part of 'base.dart';
class _InternalHelper {}
错误处理
try-catch-finally
try {
var result = await riskyOperation();
processResult(result);
} on FormatException catch (e) {
print('格式错误: $e');
} on IOException {
print('IO 错误');
} catch (e, stack) {
print('未知错误: $e\n$stack');
} finally {
await cleanup();
}
抛出自定义异常
class ValidationError extends Error {
final String message;
ValidationError(this.message);
@override
String toString() => 'ValidationError: $message';
}
void validate(String input) {
if (input.isEmpty) {
throw ValidationError('Input cannot be empty');
}
}
关键字速查
常用关键字分类
| 类别 | 关键字 |
|---|---|
| 声明 | var, final, const, late |
| 类型 | class, enum, mixin, extension, typedef |
| 函数 | Function, return, void, async, await, yield |
| 控制流 | if, else, switch, case, for, while, do, break, continue |
| 错误 | try, catch, finally, throw, on, rethrow |
| 库 | import, export, part, library, deferred, show, hide |
| 类成员 | static, get, set, operator, this, super, new |
| 修饰符 | abstract, sealed, interface, base, final(class) |
| 其他 | is, as, in, with, implements, extends, required |
Workflow: 编写规范的 Dart 函数
Task Progress
- Step 1: 确定函数的输入输出。 明确参数的数量、类型和可空性。使用命名参数(带
required)以增强可读性。 - Step 2: 声明返回类型。 如果可能返回 null 使用可空类型(
String?),如果不会返回使用Never,异步用Future<T>。 - Step 3: 处理边界情况。 在函数开头处理 null、空集合、特殊情况,使用
if (x == null) return提早返回。 - Step 4: 实现主体逻辑。 使用类型推断(
final、var),保持函数短小(建议 < 30 行)。 - Step 5: 添加文档注释。 使用
///注释说明函数功能、参数含义和返回值。 - Step 6: 运行分析器。 执行
dart analyze确保无类型错误。 - Step 7: 编写测试。 覆盖边界情况和主要用况,验证函数行为正确。
- Step 8: Feedback Loop。 运行测试 → 分析失败用例 → 修正逻辑 → 重复直到全部通过。
条件逻辑
- 如果参数超过 3 个: 使用命名参数或封装为对象。
- 如果函数内部创建 NEW 对象: 使用
final声明不可变性。 - 如果返回值可能为 null: 返回
T?而非抛异常,让调用方用??处理。 - 如果函数是纯计算(无副作用): 标记为
const或考虑提取为静态方法。 - 如果使用
switch判断多分支: 使用 Dart 3 的 switch 表达式和模式匹配,确保处理所有情况。 - 如果导入产生名称冲突: 使用
as前缀重命名,或用show/hide控制导入范围。
Examples
完整的用户输入验证
import 'dart:convert';
/// 用户注册请求的数据模型。
class RegistrationRequest {
final String username;
final String email;
final String password;
const RegistrationRequest({
required this.username,
required this.email,
required this.password,
});
factory RegistrationRequest.fromJson(String jsonStr) {
final map = jsonDecode(jsonStr) as Map<String, dynamic>;
return RegistrationRequest(
username: map['username'] as String,
email: map['email'] as String,
password: map['password'] as String,
);
}
}
/// 验证注册请求并返回错误信息列表。
/// 返回空列表表示验证通过。
List<String> validate(RegistrationRequest request) {
final errors = <String>[];
if (request.username.isEmpty) {
errors.add('用户名不能为空');
} else if (request.username.length < 3) {
errors.add('用户名至少 3 个字符');
}
if (!request.email.contains('@')) {
errors.add('邮箱格式不正确');
}
if (request.password.length < 8) {
errors.add('密码至少 8 位');
}
return errors;
}
void main() {
final valid = RegistrationRequest(
username: 'alice',
email: '[email protected]',
password: 'secure123',
);
final errors = validate(valid);
if (errors.isEmpty) {
print('验证通过!');
} else {
for (final e in errors) {
print('验证失败: $e');
}
}
}
使用集合操作符处理数据
List<int> filterAndTransform(List<int> numbers) {
return [
for (final n in numbers)
if (n > 0)
n * n
];
}
void main() {
final input = [-2, -1, 0, 1, 2, 3];
final squares = filterAndTransform(input);
print(squares); // [1, 4, 9]
}
使用 switch 表达式
String describeFruit(String fruit) => switch (fruit) {
'apple' || 'pear' => '仁果类水果',
'banana' || 'mango' => '热带水果',
'grape' || 'berry' => '浆果类',
_ => '其他水果',
};
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.