《Flutter全栈开发实战指南:从零到高级》- 02 -Dart语言快速入门

0 阅读8分钟

Dart语言快速入门:Flutter开发的基石

掌握现代跨平台开发的核心语言,开启高效移动应用开发之旅

e5456359-14c6-4ef4-8433-ca2158028886.png

引言:为什么选择Dart?

Dart是Google开发的面向对象的编程语言,专门为构建Web、服务器和移动应用而设计。作为Flutter框架的官方语言,Dart结合了JavaScript的灵活性和Java的稳健性,提供了出色的开发体验。

关键优势

  • 🚀 高性能:AOT和JIT编译支持
  • 📱 跨平台:一套代码多端运行
  • 🎯 易学习:语法类似Java/JavaScript
  • 🔥 热重载:极速开发调试体验

1. 变量与数据类型

1.1 变量声明

Dart提供了多种变量声明方式,每种都有不同的语义和用途:

void main() {
  // 1. var - 类型推断
  var name = 'Dart';        // 推断为String类型
  var version = 2.12;       // 推断为double类型
  
  // 2. dynamic - 动态类型
  dynamic dynamicValue = 'Hello';
  dynamicValue = 100;       // 可以重新赋值为不同类型
  dynamicValue = true;      // 再次改变类型
  
  // 3. final - 运行时常量
  final currentTime = DateTime.now(); // 运行时确定值
  
  // 4. const - 编译时常量
  const pi = 3.14159;
  const maxSize = 100;
  
  // 5. 显式类型声明
  String language = 'Dart';
  int year = 2024;
  double score = 95.5;
  bool isCompleted = true;
  
  print('变量声明示例完成');
}

1.2 基本数据类型

Dart的所有类型都是对象,没有原始类型(primitive types)的概念。

数值类型
void numberTypes() {
  // 整数类型
  int age = 25;
  int hex = 0xDEADBEEF;
  int population = 8000000000;
  
  // 浮点数类型
  double height = 1.75;
  double price = 9.99;
  double scientific = 1.5e6; // 1.5 × 10^6
  
  // num类型 - int和double的父类
  num flexibleNumber = 10;    // 可以是整数
  flexibleNumber = 10.5;      // 也可以是浮点数
  
  // 数值操作
  print('年龄: $age');
  print('身高: $height 米');
  print('十六进制: $hex');
  print('科学计数法: $scientific');
  
  // 类型转换
  String text = '123';
  int number = int.parse(text);
  double decimal = double.parse('3.14');
  
  String numberText = 123.toString();
  String piText = 3.14159.toStringAsFixed(2); // "3.14"
}
字符串类型
void stringTypes() {
  // 字符串声明方式
  String single = '单引号字符串';
  String double = "双引号字符串";
  String multiLine = '''
    多行
    字符串
    示例
  ''';
  
  // 字符串插值
  String name = '小明';
  int score = 95;
  String message = '$name的考试成绩是$score分';
  String calculation = '1 + 2 = ${1 + 2}';
  
  // 字符串操作
  String greeting = 'Hello, World!';
  print(greeting.length);        // 13
  print(greeting.toUpperCase()); // HELLO, WORLD!
  print(greeting.contains('World')); // true
  print(greeting.substring(7));  // World!
  
  // 原始字符串
  String raw = r'原始字符串 \n 不会转义';
  print(raw); // 输出: 原始字符串 \n 不会转义
}
布尔类型
void booleanTypes() {
  bool isActive = true;
  bool isCompleted = false;
  
  // Dart只有true是true,其他所有值都是false
  var emptyString = '';
  var zero = 0;
  var nullValue = null;
  
  print(emptyString is bool);  // false
  print(zero is bool);         // false
  
  // 条件判断
  if (isActive && !isCompleted) {
    print('任务进行中');
  }
}

1.3 集合类型

List(列表)
void listExamples() {
  // List声明方式
  List<int> numbers = [1, 2, 3, 4, 5];
  var names = ['Alice', 'Bob', 'Charlie']; // 类型推断
  List<dynamic> mixed = [1, 'hello', true, 3.14];
  
  // 固定长度List
  List<int> fixedList = List.filled(3, 0); // [0, 0, 0]
  
  // List操作
  numbers.add(6);                    // 添加元素
  numbers.insert(0, 0);              // 插入元素
  numbers.remove(3);                 // 删除元素
  numbers.removeAt(1);               // 删除指定位置元素
  
  print('列表长度: ${numbers.length}');
  print('第一个元素: ${numbers.first}');
  print('最后一个元素: ${numbers.last}');
  print('是否为空: ${numbers.isEmpty}');
  
  // List遍历
  for (int i = 0; i < numbers.length; i++) {
    print('索引$i: ${numbers[i]}');
  }
  
  // for-in循环
  for (var number in numbers) {
    print('数字: $number');
  }
  
  // forEach方法
  numbers.forEach((number) => print('元素: $number'));
  
  // 函数式编程操作
  var doubled = numbers.map((n) => n * 2).toList();
  var evens = numbers.where((n) => n % 2 == 0).toList();
  var sum = numbers.reduce((value, element) => value + element);
  
  print('翻倍: $doubled');
  print('偶数: $evens');
  print('总和: $sum');
}
Set(集合)
void setExamples() {
  // Set声明 - 自动去重
  Set<String> countries = {'China', 'USA', 'Japan', 'China'};
  print(countries); // {China, USA, Japan}
  
  var numbers = <int>{1, 2, 3, 3, 4}; // 类型推断
  print(numbers); // {1, 2, 3, 4}
  
  // Set操作
  countries.add('UK');
  countries.remove('Japan');
  print('包含USA: ${countries.contains('USA')}');
  
  // 集合运算
  Set<int> setA = {1, 2, 3, 4};
  Set<int> setB = {3, 4, 5, 6};
  
  print('并集: ${setA.union(setB)}');        // {1, 2, 3, 4, 5, 6}
  print('交集: ${setA.intersection(setB)}'); // {3, 4}
  print('差集: ${setA.difference(setB)}');   // {1, 2}
}
Map(映射)
void mapExamples() {
  // Map声明
  Map<String, String> capitals = {
    'China': 'Beijing',
    'USA': 'Washington',
    'Japan': 'Tokyo',
  };
  
  var scores = <String, int>{ // 类型推断
    'Alice': 95,
    'Bob': 87,
    'Charlie': 92,
  };
  
  // Map操作
  capitals['UK'] = 'London';      // 添加键值对
  capitals['Japan'] = '東京';      // 更新值
  capitals.remove('USA');         // 删除键值对
  
  print('中国首都: ${capitals['China']}');
  print('包含法国: ${capitals.containsKey('France')}');
  
  // Map遍历
  capitals.forEach((key, value) {
    print('$key 的首都是 $value');
  });
  
  for (var entry in capitals.entries) {
    print('${entry.key}: ${entry.value}');
  }
  
  // 键和值的集合
  print('所有国家: ${capitals.keys.toList()}');
  print('所有首都: ${capitals.values.toList()}');
}

1.4 空安全

Dart的空安全特性帮助在编译时捕获空引用错误:

void nullSafety() {
  // 不可空类型
  String name = 'Dart';  // 不能为null
  // name = null;        // 编译错误
  
  // 可空类型
  String? nullableName;  // 可以为null
  nullableName = null;   // 允许赋值为null
  nullableName = 'Dart'; // 也可以赋值为非null
  
  // 空安全操作符
  String? maybeName;
  
  // 安全调用操作符 ?.
  int? length = maybeName?.length;
  
  // 空值合并操作符 ??
  String displayName = maybeName ?? '未知用户';
  
  // 空断言操作符 !
  String definitelyName = maybeName!; // 断言不为null
  
  // 空安全检查
  if (maybeName != null) {
    // 在这个作用域内,Dart知道maybeName不为null
    print(maybeName.length);
  }
  
  print('空安全示例完成');
}

2. 函数与面向对象

2.1 函数基础

Dart中的函数是一等公民,可以作为参数传递和返回值。

// 基本函数声明
int add(int a, int b) {
  return a + b;
}

// 箭头函数(单行函数)
int multiply(int a, int b) => a * b;

// 可选参数函数
void userProfile(String name, [int? age, String? city]) {
  print('姓名: $name');
  if (age != null) print('年龄: $age');
  if (city != null) print('城市: $city');
}

// 命名参数函数
void createUser({required String name, int age = 0, String? email}) {
  print('创建用户: $name, $age岁');
  if (email != null) print('邮箱: $email');
}

// 函数作为参数
void executeOperation(int a, int b, int Function(int, int) operation) {
  var result = operation(a, b);
  print('操作结果: $result');
}

void functionExamples() {
  // 调用基本函数
  var sum = add(5, 3);
  print('5 + 3 = $sum');
  
  // 调用箭头函数
  var product = multiply(4, 7);
  print('4 × 7 = $product');
  
  // 调用可选参数函数
  userProfile('Alice');
  userProfile('Bob', 25);
  userProfile('Charlie', 30, 'New York');
  
  // 调用命名参数函数
  createUser(name: 'David');
  createUser(name: 'Eva', age: 28);
  createUser(name: 'Frank', age: 35, email: 'frank@example.com');
  
  // 传递函数作为参数
  executeOperation(10, 5, add);
  executeOperation(10, 5, multiply);
  executeOperation(10, 5, (a, b) => a - b); // 匿名函数
}

2.2 匿名函数与高阶函数

void anonymousFunctionExamples() {
  var numbers = [1, 2, 3, 4, 5];
  
  // 匿名函数
  numbers.forEach((number) {
    print('数字: $number');
  });
  
  // 更简洁的匿名函数
  numbers.forEach((number) => print('数值: $number'));
  
  // 函数赋值给变量
  var shout = (String message) => message.toUpperCase() + '!';
  print(shout('hello dart'));
  
  // 返回函数的函数
  Function multiplier(int factor) {
    return (int value) => value * factor;
  }
  
  var doubleIt = multiplier(2);
  var tripleIt = multiplier(3);
  
  print('双倍: ${doubleIt(5)}'); // 10
  print('三倍: ${tripleIt(5)}'); // 15
  
  // 函数组合
  String capitalize(String text) => text[0].toUpperCase() + text.substring(1);
  String addExclamation(String text) => text + '!';
  
  var transform = (String text) => addExclamation(capitalize(text));
  print(transform('hello world')); // Hello world!
}

2.3 类与对象

基础类定义
class Person {
  // 实例变量
  String name;
  int age;
  
  // 构造函数
  Person(this.name, this.age);
  
  // 命名构造函数
  Person.newborn(String name) : this(name, 0);
  
  // 方法
  void introduce() {
    print('你好,我是$name,今年$age岁');
  }
  
  // Getter
  String get description => '$name ($age岁)';
  
  // Setter
  set birthday(DateTime date) {
    var now = DateTime.now();
    age = now.year - date.year;
  }
  
  // 重写toString方法
  @override
  String toString() => 'Person{name: $name, age: $age}';
}

void classExamples() {
  // 创建对象
  var alice = Person('Alice', 25);
  var baby = Person.newborn('Baby');
  
  // 调用方法
  alice.introduce();
  baby.introduce();
  
  // 使用Getter
  print(alice.description);
  
  // 使用Setter
  alice.birthday = DateTime(1998, 5, 15);
  print('更新后年龄: ${alice.age}');
  
  print(alice.toString());
}
继承与多态
// 基类
class Animal {
  String name;
  int age;
  
  Animal(this.name, this.age);
  
  void makeSound() {
    print('动物发出声音');
  }
  
  void sleep() {
    print('$name 在睡觉');
  }
}

// 继承
class Dog extends Animal {
  String breed;
  
  Dog(String name, int age, this.breed) : super(name, age);
  
  // 方法重写
  @override
  void makeSound() {
    print('$name 汪汪叫!');
  }
  
  // 新增方法
  void fetch() {
    print('$name 在接飞盘');
  }
}

class Cat extends Animal {
  Cat(String name, int age) : super(name, age);
  
  @override
  void makeSound() {
    print('$name 喵喵叫!');
  }
  
  void climb() {
    print('$name 在爬树');
  }
}

void inheritanceExamples() {
  // 多态
  Animal myDog = Dog('Buddy', 3, 'Golden Retriever');
  Animal myCat = Cat('Whiskers', 2);
  
  // 运行时多态
  myDog.makeSound(); // Buddy 汪汪叫!
  myCat.makeSound(); // Whiskers 喵喵叫!
  
  // 类型检查和转换
  if (myDog is Dog) {
    (myDog as Dog).fetch(); // 类型转换后调用子类方法
  }
  
  List<Animal> animals = [myDog, myCat];
  for (var animal in animals) {
    animal.makeSound(); // 多态调用
  }
}
抽象类与接口
// 抽象类
abstract class Shape {
  // 抽象方法
  double area();
  double perimeter();
  
  // 具体方法
  void describe() {
    print('这个形状的面积是 ${area()},周长是 ${perimeter()}');
  }
}

// 实现抽象类
class Rectangle extends Shape {
  double width;
  double height;
  
  Rectangle(this.width, this.height);
  
  @override
  double area() => width * height;
  
  @override
  double perimeter() => 2 * (width + height);
}

class Circle extends Shape {
  double radius;
  
  Circle(this.radius);
  
  @override
  double area() => 3.14159 * radius * radius;
  
  @override
  double perimeter() => 2 * 3.14159 * radius;
}

// 接口(在Dart中每个类都隐式定义了一个接口)
class Square implements Shape {
  double side;
  
  Square(this.side);
  
  @override
  double area() => side * side;
  
  @override
  double perimeter() => 4 * side;
  
  @override
  void describe() {
    print('这个正方形的边长是 $side,面积是 ${area()}');
  }
}

void abstractClassExamples() {
  List<Shape> shapes = [
    Rectangle(5, 3),
    Circle(4),
    Square(6),
  ];
  
  for (var shape in shapes) {
    shape.describe();
  }
}
Mixin(混入)
// Mixin定义
mixin Flyable {
  void fly() {
    print('在空中飞翔');
  }
}

mixin Swimmable {
  void swim() {
    print('在水中游泳');
  }
}

mixin Runnable {
  void run() {
    print('在陆地上奔跑');
  }
}

// 使用Mixin
class Bird with Flyable, Runnable {
  String name;
  
  Bird(this.name);
  
  void describe() {
    print('$name 可以:');
    fly();
    run();
  }
}

class Duck with Flyable, Swimmable, Runnable {
  String name;
  
  Duck(this.name);
  
  void describe() {
    print('$name 可以:');
    fly();
    swim();
    run();
  }
}

void mixinExamples() {
  var sparrow = Bird('麻雀');
  var duck = Duck('鸭子');
  
  sparrow.describe();
  print('---');
  duck.describe();
}

3. 异步编程(Future/Stream)

3.1 Future基础

Future表示一个可能在未来完成的计算或操作。

import 'dart:async';

// 模拟异步操作
Future<String> fetchUserData() {
  return Future.delayed(Duration(seconds: 2), () => '用户数据加载完成');
}

Future<int> fetchUserScore() {
  return Future.delayed(Duration(seconds: 1), () => 95);
}

void futureBasicExamples() async {
  print('开始获取用户数据...');
  
  // 使用then处理Future完成
  fetchUserData().then((data) {
    print('收到数据: $data');
  }).catchError((error) {
    print('发生错误: $error');
  });
  
  // 使用async/await(更推荐)
  try {
    var data = await fetchUserData();
    print('使用await收到数据: $data');
  } catch (error) {
    print('发生错误: $error');
  }
  
  // 多个Future处理
  var userData = fetchUserData();
  var userScore = fetchUserScore();
  
  // 等待所有Future完成
  var results = await Future.wait([userData, userScore]);
  print('所有结果: $results');
  
  // Future链式操作
  var processedData = await fetchUserData()
      .then((data) => data.toUpperCase())
      .then((data) => '处理后的: $data');
  
  print(processedData);
}

3.2 高级Future用法

Future<String> loginUser(String username, String password) async {
  await Future.delayed(Duration(seconds: 1));
  
  if (username == 'admin' && password == '123456') {
    return '登录成功';
  } else {
    throw Exception('用户名或密码错误');
  }
}

Future<String> getUserProfile(String token) async {
  await Future.delayed(Duration(seconds: 2));
  return '用户资料: 姓名: 张三, 年龄: 25';
}

void advancedFutureExamples() async {
  // Future.error创建错误Future
  var errorFuture = Future.error(Exception('自定义错误'));
  
  // Future.value创建立即完成的Future
  var immediateFuture = Future.value('立即完成的值');
  
  // 超时控制
  try {
    var result = await fetchUserData().timeout(
      Duration(seconds: 1),
      onTimeout: () => '请求超时,返回默认值'
    );
    print('超时控制结果: $result');
  } catch (e) {
    print('超时错误: $e');
  }
  
  // 模拟登录流程
  try {
    var token = await loginUser('admin', '123456');
    print('登录结果: $token');
    
    var profile = await getUserProfile(token);
    print('用户资料: $profile');
  } catch (e) {
    print('登录失败: $e');
  }
  
  // Future微任务
  print('开始');
  
  Future(() => print('普通任务'));
  Future.microtask(() => print('微任务'));
  
  print('结束');
  // 输出顺序: 开始 → 结束 → 微任务 → 普通任务
}

3.3 Stream基础

Stream表示一系列异步事件。

import 'dart:async';

// 创建Stream
Stream<int> countStream(int max) async* {
  for (int i = 1; i <= max; i++) {
    await Future.delayed(Duration(milliseconds: 500));
    yield i; // 产生流数据
  }
}

// 转换Stream
Stream<String> stringStream(int max) async* {
  for (int i = 1; i <= max; i++) {
    await Future.delayed(Duration(milliseconds: 300));
    yield '项目 $i';
  }
}

void streamBasicExamples() async {
  print('开始Stream示例...');
  
  // 监听Stream
  var subscription = countStream(5).listen(
    (data) => print('收到数据: $data'),
    onError: (error) => print('错误: $error'),
    onDone: () => print('Stream完成'),
    cancelOnError: false,
  );
  
  // 等待Stream完成
  await subscription.asFuture();
  
  print('--- Stream转换 ---');
  
  // 使用await for处理Stream
  await for (var number in countStream(3)) {
    print('await for: $number');
  }
  
  print('--- Stream操作 ---');
  
  // Stream转换操作
  var transformed = countStream(4)
      .where((number) => number % 2 == 0)  // 过滤偶数
      .map((number) => number * 10)        // 转换数据
      .take(2);                            // 取前2个
  
  await for (var value in transformed) {
    print('转换后的值: $value');
  }
}

3.4 高级Stream用法

class DataService {
  final StreamController<String> _controller = StreamController<String>();
  
  // 公开的Stream
  Stream<String> get dataStream => _controller.stream;
  
  // 添加数据到Stream
  void addData(String data) {
    _controller.add(data);
  }
  
  // 添加错误到Stream
  void addError(String error) {
    _controller.addError(error);
  }
  
  // 关闭Stream
  void close() {
    _controller.close();
  }
}

void advancedStreamExamples() async {
  var service = DataService();
  
  // 广播Stream(允许多个监听器)
  var broadcastStream = service.dataStream.asBroadcastStream();
  
  // 第一个监听器
  var subscription1 = broadcastStream.listen(
    (data) => print('监听器1: $data'),
    onError: (error) => print('监听器1错误: $error'),
    onDone: () => print('监听器1: Stream关闭'),
  );
  
  // 第二个监听器
  var subscription2 = broadcastStream.listen(
    (data) => print('监听器2: $data'),
  );
  
  // 模拟数据产生
  service.addData('第一条数据');
  await Future.delayed(Duration(seconds: 1));
  
  service.addData('第二条数据');
  await Future.delayed(Duration(seconds: 1));
  
  service.addError('模拟错误');
  await Future.delayed(Duration(seconds: 1));
  
  service.addData('最后一条数据');
  
  // 关闭Stream
  service.close();
  
  // 取消订阅
  await Future.delayed(Duration(seconds: 2));
  subscription1.cancel();
  subscription2.cancel();
  
  print('--- Stream进阶操作 ---');
  
  // Stream.reduce
  var numberStream = Stream.fromIterable([1, 2, 3, 4, 5]);
  var sum = await numberStream.reduce((a, b) => a + b);
  print('Stream.reduce结果: $sum'); // 15
  
  // Stream.toList
  var listStream = Stream.fromIterable(['A', 'B', 'C']);
  var list = await listStream.toList();
  print('Stream.toList结果: $list'); // [A, B, C]
  
  // Stream缓冲
  var bufferedStream = countStream(10).bufferCount(3);
  await for (var buffer in bufferedStream) {
    print('缓冲数据: $buffer'); // [1,2,3], [4,5,6], [7,8,9], [10]
  }
}

4. Dart特有语法糖

4.1 级联操作符(..)

级联操作符允许对同一对象执行一系列操作。

class Button {
  String text = '';
  String color = 'blue';
  double width = 100.0;
  double height = 50.0;
  bool isEnabled = true;
  
  void click() {
    print('按钮被点击: $text');
  }
  
  @override
  String toString() => '按钮: $text, 颜色: $color, 尺寸: ${width}x$height';
}

void cascadeNotationExamples() {
  // 传统方式
  var button1 = Button();
  button1.text = '提交';
  button1.color = 'green';
  button1.width = 120.0;
  button1.click();
  
  // 使用级联操作符
  var button2 = Button()
    ..text = '取消'
    ..color = 'red'
    ..width = 80.0
    ..height = 40.0
    ..click();
  
  print(button1);
  print(button2);
  
  // 嵌套级联
  var complexButton = Button()
    ..text = '复杂按钮'
    ..color = 'purple'
    ..width = 200.0
    ..height = 60.0
    ..click()
    ..text = '更新后的文本'
    ..click();
  
  print(complexButton);
  
  // 在列表中使用级联
  var buttons = <Button>[
    Button()..text = '按钮1'..color = 'blue',
    Button()..text = '按钮2'..color = 'green',
    Button()..text = '按钮3'..color = 'red',
  ];
  
  for (var button in buttons) {
    print(button);
  }
}

4.2 空安全操作符

class User {
  String? name;
  int? age;
  Address? address;
  
  User({this.name, this.age, this.address});
}

class Address {
  String? street;
  String? city;
  
  Address({this.street, this.city});
}

void nullAwareOperators() {
  // ?. 安全调用操作符
  User? user;
  print(user?.name); // 输出: null,不会抛出异常
  
  user = User(name: 'Alice', address: Address(street: '123 Main St'));
  print(user?.name); // 输出: Alice
  print(user?.address?.city); // 输出: null
  
  // ?? 空值合并操作符
  String? nullableName;
  String displayName = nullableName ?? '未知用户';
  print(displayName); // 输出: 未知用户
  
  // ??= 空值赋值操作符
  String? currentUser;
  currentUser ??= '默认用户';
  print(currentUser); // 输出: 默认用户
  
  // ...? 空感知展开操作符
  List<int>? nullableList;
  List<int> combined = [1, 2, 3, ...?nullableList];
  print(combined); // 输出: [1, 2, 3]
  
  // ! 空断言操作符(谨慎使用)
  User definiteUser = User(name: 'Bob')!;
  print(definiteUser.name);
}

4.3 扩展方法

扩展方法允许向现有类添加新功能。

// 为int类型添加扩展
extension IntExtensions on int {
  // 判断是否为偶数
  bool get isEven => this % 2 == 0;
  
  // 判断是否为奇数
  bool get isOdd => this % 2 == 1;
  
  // 转换为时间间隔
  Duration get seconds => Duration(seconds: this);
  Duration get minutes => Duration(minutes: this);
  Duration get hours => Duration(hours: this);
  
  // 重复执行操作
  void times(Function(int) action) {
    for (int i = 0; i < this; i++) {
      action(i);
    }
  }
}

// 为String类型添加扩展
extension StringExtensions on String {
  // 反转字符串
  String get reversed => split('').reversed.join();
  
  // 判断是否为电子邮件
  bool get isEmail => contains('@') && contains('.');
  
  // 转换为标题格式
  String toTitleCase() {
    if (isEmpty) return this;
    return this[0].toUpperCase() + substring(1).toLowerCase();
  }
  
  // 解析为int,失败返回null
  int? toIntOrNull() => int.tryParse(this);
}

void extensionMethodsExamples() {
  // 使用int扩展
  print(5.isEven); // false
  print(5.isOdd);  // true
  
  print(3.times((i) => print('重复 $i 次')));
  // 输出:
  // 重复 0 次
  // 重复 1 次  
  // 重复 2 次
  
  // 使用Duration扩展
  Future.delayed(2.seconds, () => print('2秒后执行'));
  
  // 使用String扩展
  print('hello'.reversed); // olleh
  print('test@example.com'.isEmail); // true
  print('dart language'.toTitleCase()); // Dart language
  print('123'.toIntOrNull()); // 123
  print('abc'.toIntOrNull()); // null
}

4.4 集合字面量与操作符

void collectionLiteralsAndOperators() {
  // 集合if
  var shouldIncludeExtra = true;
  var items = [
    '基础项目1',
    '基础项目2',
    if (shouldIncludeExtra) '额外项目',
  ];
  print(items); // [基础项目1, 基础项目2, 额外项目]
  
  // 集合for
  var numbers = [1, 2, 3];
  var doubledNumbers = [
    for (var number in numbers) number * 2,
  ];
  print(doubledNumbers); // [2, 4, 6]
  
  // 展开操作符
  var list1 = [1, 2, 3];
  var list2 = [4, 5, 6];
  var combined = [...list1, ...list2];
  print(combined); // [1, 2, 3, 4, 5, 6]
  
  // Map字面量增强
  var map = {
    'name': 'Alice',
    'age': 25,
    if (shouldIncludeExtra) 'city': 'Beijing',
    for (var i in [1, 2, 3]) 'key$i': 'value$i',
  };
  print(map);
  // {name: Alice, age: 25, city: Beijing, key1: value1, key2: value2, key3: value3}
  
  // Set字面量增强
  var set = {
    1, 2, 3,
    if (shouldIncludeExtra) 4,
    for (var i in [1, 2]) i * 10,
  };
  print(set); // {1, 2, 3, 4, 10, 20}
}

4.5 其他实用语法糖

void otherSyntaxSugar() {
  // 条件属性访问
  String? maybeString;
  print(maybeString?.length); // null
  
  // 使用[]访问Map的简洁方式
  var config = {'theme': 'dark', 'language': 'zh'};
  print(config['theme']); // dark
  
  // 函数简写
  var numbers = [1, 2, 3, 4, 5];
  var evens = numbers.where((n) => n.isEven); // 简写形式
  print(evens); // (2, 4)
  
  // 字符串多行和插值
  var name = 'Dart';
  var version = 2.12;
  var message = '''
    欢迎使用 $name!
    当前版本: $version
    下一个版本: ${version + 0.1}
  ''';
  print(message);
  
  // 类型测试和转换的简写
  var value = 'Hello';
  if (value is String) {
    print(value.length); // 自动转换为String类型
  }
  
  // 使用as进行显式类型转换
  (value as String).toUpperCase();
}

实战项目:简单的待办事项应用

让我们用学到的Dart知识构建一个简单的待办事项应用:

class TodoItem {
  final String id;
  String title;
  bool isCompleted;
  DateTime createdAt;
  
  TodoItem({
    required this.title,
    this.isCompleted = false,
  }) : id = DateTime.now().millisecondsSinceEpoch.toString(),
       createdAt = DateTime.now();
  
  void toggleComplete() {
    isCompleted = !isCompleted;
  }
  
  @override
  String toString() => '[${isCompleted ? '✓' : ' '}] $title';
}

class TodoManager {
  final List<TodoItem> _items = [];
  
  // 添加待办事项
  void addTodo(String title) {
    _items.add(TodoItem(title: title));
    print('添加待办: $title');
  }
  
  // 完成待办事项
  void completeTodo(String id) {
    var item = _items.firstWhere((item) => item.id == id);
    item.toggleComplete();
    print('完成待办: ${item.title}');
  }
  
  // 删除待办事项
  void removeTodo(String id) {
    _items.removeWhere((item) => item.id == id);
    print('删除待办');
  }
  
  // 获取所有待办事项
  List<TodoItem> get todos => List.unmodifiable(_items);
  
  // 获取未完成事项
  List<TodoItem> get pendingTodos => 
      _items.where((item) => !item.isCompleted).toList();
  
  // 获取已完成事项
  List<TodoItem> get completedTodos => 
      _items.where((item) => item.isCompleted).toList();
  
  // 清空所有事项
  void clearAll() {
    _items.clear();
    print('清空所有待办事项');
  }
  
  // 显示统计信息
  void showStats() {
    print('''
=== 待办事项统计 ===
总计: ${_items.length}
待完成: ${pendingTodos.length}
已完成: ${completedTodos.length}
完成率: ${_items.isEmpty ? 0 : (completedTodos.length / _items.length * 100).toStringAsFixed(1)}%
===============
    ''');
  }
}

void todoAppExample() async {
  var manager = TodoManager();
  
  print('🚀 启动待办事项应用...\n');
  
  // 添加待办事项
  manager.addTodo('学习Dart基础语法');
  manager.addTodo('练习Future和Stream');
  manager.addTodo('构建Flutter应用');
  
  await Future.delayed(1.seconds);
  
  // 显示所有事项
  print('\n📋 所有待办事项:');
  manager.todos.forEach(print);
  
  await Future.delayed(1.seconds);
  
  // 完成第一个事项
  if (manager.todos.isNotEmpty) {
    manager.completeTodo(manager.todos.first.id);
  }
  
  await Future.delayed(1.seconds);
  
  // 显示统计
  manager.showStats();
  
  await Future.delayed(1.seconds);
  
  // 显示未完成事项
  print('⏳ 未完成事项:');
  manager.pendingTodos.forEach(print);
  
  await Future.delayed(1.seconds);
  
  // 完成所有事项
  print('\n🎯 批量完成所有事项...');
  for (var todo in manager.pendingTodos) {
    manager.completeTodo(todo.id);
    await Future.delayed(500.milliseconds);
  }
  
  // 最终统计
  manager.showStats();
}

void main() async {
  // 运行待办事项应用示例
  await todoAppExample();
  
  print('\n✨ Dart语言快速入门学习完成!');
  print('接下来可以开始学习Flutter框架了!');
}

学习资源与下一步

推荐学习路径

  1. 巩固Dart基础:熟练掌握本文介绍的核心概念
  2. 实践小项目:用Dart构建命令行工具或简单应用
  3. 学习Flutter:将Dart知识应用到Flutter开发中
  4. 深入高级特性:学习Isolate、泛型、元编程等

实用资源

常见问题解答

Q: Dart与JavaScript/TypeScript有什么区别? A: Dart是强类型语言,有更好的工具支持和性能表现,特别适合构建大型应用。

Q: 学习Dart需要什么基础? A: 如果有Java、C#、JavaScript或Python经验,学习Dart会很容易。

Q: Dart只能用于Flutter吗? A: 不,Dart也可以用于Web后端开发(使用Aqueduct等框架)和命令行工具。