Skip to content

Dart 语法速查

Flutter 使用 Dart 语言开发。本文按照从简单到复杂的顺序,逐一讲解 Dart 最核心的语法,每一条都配有「是什么 → 怎么写 → 什么时候用」的说明。

1. 变量:存数据的容器

1.1 声明方式

Dart 有三种声明变量的关键字,选择逻辑很简单:

关键字含义何时用
var让 Dart 自动猜类型大多数场景(推荐)
final赋值一次后不能再改运行时才能确定的值(如网络请求结果)
const编译时就确定的常量永远不变的值(如数学常量)
dart
// var —— 自动推断类型,最常用
var name = 'Flutter';   // Dart 自动知道 name 是 String
var count = 42;          // Dart 自动知道 count 是 int

// final —— 只能赋值一次,之后不能改
final now = DateTime.now(); // 运行时才有值,用 final

// const —— 编译时就确定,永远不变
const pi = 3.14;            // π 永远不变,用 const

💡 简单记忆:能用 const 就用 const,否则用 final,都不合适再用 var

1.2 基本数据类型

Dart 常用的基础类型只有四个:

dart
String  text = '你好';      // 字符串,用单引号或双引号
int     age  = 18;          // 整数
double  pi  = 3.14;         // 小数(没有 float,只有 double)
bool    ok  = true;         // 布尔值,只有 true / false

1.3 空安全(Null Safety)

这是 Dart 和很多语言不同的地方:默认情况下变量不能为 null

dart
String name = 'Tom';
// name = null;  ❌ 编译报错!String 不允许为空

// 如果确实需要"可能没有值",加个问号
String? nickname;    // ✅ String? 表示"字符串或空"
nickname = null;     // ✅ 允许
nickname = 'Jack';  // ✅ 也允许

使用可空变量时,需要安全处理:

dart
String? nickname;

// 方式一:用 ?. 安全调用(如果是 null 就不执行,返回 null)
int? len = nickname?.length;  // nickname 为 null 时,len 也为 null

// 方式二:用 ?? 提供默认值(如果是 null 就用后面的值)
int len = nickname?.length ?? 0;  // nickname 为 null 时,len = 0

// 方式三:用 ! 强制断言非空(确定不为 null 时才用,否则报错)
// String upper = nickname!.toUpperCase();  ⚠️ 确定不为 null 才能用

💡 记住一句话:? 表示"可以为空",不加就不能为空。这是 Dart 防止空指针错误的核心机制。

2. 字符串:最常用的操作

dart
var name = 'Flutter';
var version = 3;

// 字符串插值:用 $ 变量名 或 ${表达式}
print('Hello $name');              // Hello Flutter
print('Version: $version');        // Version: 3
print('Upper: ${name.toUpperCase()}');  // Upper: FLUTTER

// 多行字符串
var message = '''
  第一行
  第二行
  第三行
''';

// 字符串拼接
var full = 'Hello' + ' ' + 'World';  // 'Hello World'

3. 集合:装多个数据

3.1 List —— 有序列表(最常用)

dart
// 创建
var fruits = ['苹果', '香蕉', '橘子'];  // 自动推断为 List<String>

// 增删改查
fruits.add('葡萄');          // 末尾添加
fruits.remove('香蕉');        // 按值删除
fruits[0];                    // 取第一个 → '苹果'
fruits.length;                // 长度 → 3

// 遍历
for (var fruit in fruits) {
  print(fruit);
}

3.2 Map —— 键值对(类似字典)

dart
// 创建
var scores = {
  'Alice': 90,
  'Bob': 85,
};

// 增删改查
scores['Charlie'] = 95;      // 添加 / 修改
scores.remove('Bob');         // 删除
scores['Alice'];              // 取值 → 90

// 遍历
scores.forEach((key, value) {
  print('$key: $value');
});

3.3 Set —— 不重复的集合

dart
var numbers = {1, 2, 3, 3, 4};  // 自动去重 → {1, 2, 3, 4}
numbers.add(5);
numbers.contains(3);  // true

3.4 常用集合操作

这些方法在 Flutter 开发中非常常用,建议记住:

dart
var fruits = ['apple', 'banana', 'avocado'];

// 过滤:挑出符合条件的
var aFruits = fruits.where((f) => f.startsWith('a')).toList();
// → ['apple', 'avocado']

// 转换:对每个元素做变换
var upper = fruits.map((f) => f.toUpperCase()).toList();
// → ['APPLE', 'BANANA', 'AVOCADO']

// 判断:是否包含满足条件的元素
var hasApple = fruits.any((f) => f == 'apple');  // true

// 排序
var sorted = [3, 1, 2]..sort();  // [1, 2, 3]

4. 函数:可复用的代码块

4.1 基本写法

dart
// 标准写法
int add(int a, int b) {
  return a + b;
}

// 箭头写法(函数体只有一个表达式时,可用 => 简写)
int add(int a, int b) => a + b;

4.2 参数

Dart 的参数规则是一大特色,记住这两种就够了:

dart
// ① 命名参数 { } —— 调用时必须写参数名(Flutter 组件大量使用这种)
void greet({required String name, int age = 0}) {
  print('你好,$name,年龄 $age');
}
greet(name: 'Tom', age: 25);    // ✅ 调用时写参数名
greet(name: 'Tom');              // ✅ age 有默认值,可以不传

// ② 位置参数 [ ] —— 按顺序传,可以不传
void hello(String name, [String? city]) {
  print('你好,$name${city != null ? ",来自$city" : ""}');
}
hello('Tom', '北京');  // 你好,Tom,来自北京
hello('Tom');          // 你好,Tom

💡 Flutter 开发中 90% 是命名参数,因为可读性好:Text('内容', style: TextStyle(fontSize: 16)) 比位置参数清晰得多。

4.3 函数作为参数(回调)

在 Flutter 中,点击事件、列表项构建等都用到了"函数当参数":

dart
// 定义:接受一个函数作为参数
void doSomething(int Function(int, int) operation) {
  print(operation(3, 4));
}

// 调用:传入匿名函数
doSomething((a, b) => a + b);  // 输出 7
doSomething((a, b) => a * b);  // 输出 12

5. 控制流:程序的执行逻辑

5.1 条件判断

dart
// if-else
var score = 85;
if (score >= 90) {
  print('优秀');
} else if (score >= 60) {
  print('及格');
} else {
  print('不及格');
}

// 三目运算符(简写的 if-else)
var result = score >= 60 ? 'Pass' : 'Fail';  // 'Pass'

5.2 循环

dart
// for 循环
for (var i = 0; i < 5; i++) {
  print(i);  // 0 1 2 3 4
}

// for-in 循环(遍历集合,更常用)
var fruits = ['苹果', '香蕉'];
for (var fruit in fruits) {
  print(fruit);
}

// while 循环
var i = 0;
while (i < 5) {
  print(i);
  i++;
}

5.3 switch

dart
var color = 'red';
switch (color) {
  case 'red':
    print('红色');
    break;
  case 'blue':
    print('蓝色');
    break;
  default:
    print('其他颜色');
}

6. 类:面向对象的基础

类是 Dart 的核心概念,Flutter 中一切 Widget 都是类

6.1 定义和使用类

dart
class Person {
  // 属性
  String name;
  int age;

  // 构造函数:Person(this.name, this.age) 是简写
  Person(this.name, this.age);

  // 方法
  void sayHello() {
    print('你好,我是$name,今年$age岁');
  }

  // Getter:像属性一样访问,但实际是计算出来的
  bool get isAdult => age >= 18;
}

// 使用
var p = Person('Tom', 25);
p.sayHello();      // 你好,我是Tom,今年25岁
print(p.isAdult);  // true(像属性一样用,不加括号)

6.2 命名构造函数

一个类可以有多个构造函数,用名字区分:

dart
class Person {
  String name;
  int age;

  Person(this.name, this.age);

  // 命名构造函数:从 Map 创建对象
  Person.fromJson(Map<String, dynamic> json)
      : name = json['name'],
        age = json['age'];
}

// 使用
var p1 = Person('Tom', 25);
var p2 = Person.fromJson({'name': 'Jerry', 'age': 30});

6.3 继承:子类获得父类的能力

dart
class Animal {
  String name;
  Animal(this.name);

  void speak() => print('$name 发出声音');
}

// Dog 继承 Animal,获得 name 和 speak()
class Dog extends Animal {
  String breed;
  Dog(String name, this.breed) : super(name);  // super 调用父类构造函数

  @override  // 重写父类方法
  void speak() => print('$name 汪汪汪!(品种:$breed)');
}

var dog = Dog('旺财', '柯基');
dog.speak();  // 旺财 汪汪汪!(品种:柯基)

6.4 抽象类:只定义规范,不实现

dart
// 抽象类:定义"长什么样",但不实现细节
abstract class Shape {
  double get area;  // 只有声明,没有实现
  void draw();      // 只有声明,没有实现
}

// 具体类必须实现抽象类的所有方法
class Circle extends Shape {
  double radius;
  Circle(this.radius);

  @override
  double get area => 3.14 * radius * radius;

  @override
  void draw() => print('画一个半径为$radius的圆');
}

6.5 Mixin:给类"混入"额外能力

Mixin 不是继承,而是额外能力叠加,可以理解为"插件":

dart
mixin Flyable {
  void fly() => print('飞起来了!');
}

mixin Swimmable {
  void swim() => print('游起来了!');
}

// 用 with 混入能力,一个类可以混入多个
class Duck extends Animal with Flyable, Swimmable {
  Duck(String name) : super(name);
}

var duck = Duck('唐老鸭');
duck.speak();  // 唐老鸭 发出声音
duck.fly();    // 飞起来了!
duck.swim();   // 游起来了!

💡 继承(extends)是"是什么",Mixin(with)是"能做什么"。一个类只能继承一个父类,但可以混入多个 Mixin。

7. 异步编程:等一等再继续

Flutter 开发中,网络请求、文件读写等都是异步操作。Dart 用 async / await 处理异步,非常直观。

7.1 Future —— 等一个结果

Future 就是"未来的值",类似于其他语言的 Promise

dart
// 定义异步函数:加 async 关键字
Future<String> fetchName() async {
  // await 等待耗时操作完成
  await Future.delayed(Duration(seconds: 1));  // 模拟耗时 1 秒
  return 'Flutter';
}

// 使用异步函数
void main() async {  // 使用 await 的函数也必须加 async
  print('开始');
  String name = await fetchName();  // 等待结果
  print(name);  // 1 秒后输出:Flutter
}

💡 规则很简单:函数加 async,调用加 await,返回值用 Future 包一下。

7.2 错误处理

dart
Future<void> loadData() async {
  try {
    final result = await fetchData();  // 可能出错的异步操作
    print(result);
  } catch (e) {
    print('出错了:$e');  // 捕获错误
  } finally {
    print('无论如何都执行');  // 可选
  }
}

7.3 Stream —— 持续接收数据

Future 是等一个结果,Stream 是持续接收多个结果(比如聊天消息、传感器数据):

dart
// 定义:用 async* 和 yield 产生数据流
Stream<int> countDown(int from) async* {
  for (int i = from; i > 0; i--) {
    await Future.delayed(Duration(seconds: 1));
    yield i;  // yield 产生一个值,但不结束函数
  }
}

// 使用:listen 监听数据流
countDown(3).listen((value) {
  print(value);  // 每秒输出:3 → 2 → 1
});

💡 Future vs Stream:Future = 一次性的结果;Stream = 持续不断的数据流。

8. 枚举与扩展

8.1 枚举(enum):限定选项

dart
enum Status { loading, success, error }

var current = Status.loading;

// 在 switch 中使用(Dart 会提示你处理所有情况)
switch (current) {
  case Status.loading:
    print('加载中');
    break;
  case Status.success:
    print('成功');
    break;
  case Status.error:
    print('出错了');
    break;
}

8.2 扩展方法:给已有类型加新功能

dart
// 给 String 加一个 reversed 属性
extension StringExtension on String {
  String get reversed => split('').reversed.join();
}

// 使用
print('hello'.reversed);  // 'olleh'

9. 其他实用语法

9.1 级联操作符 ..

连续操作同一个对象,不用反复写变量名:

dart
// 不用级联
var paint = Paint();
paint.color = Colors.blue;
paint.strokeWidth = 5.0;

// 用级联(更简洁)
var paint = Paint()
  ..color = Colors.blue
  ..strokeWidth = 5.0;

9.2 类型判断

dart
var value = 'hello';

// is 判断类型(成立后自动类型转换)
if (value is String) {
  print(value.length);  // 这里 value 自动被识别为 String
}

// as 强制类型转换(确定类型时用)
var len = (value as String).length;

9.3 空值合并

dart
String? name;
String displayName = name ?? '匿名';  // name 为 null 就用 '匿名'

提示

以上是 Dart 在 Flutter 开发中最常用的语法。更完整的语法参考请查看 Dart 语言指南

基于 Flutter 官方文档整理