Dart 基础教程

230 阅读5分钟

Dart 基础教程

Dart 是由 Google 开发的一种开源、通用的编程语言,主要用于构建跨平台的应用程序,尤其是 Flutter 应用。Dart 具有面向对象的特性,支持类、接口、混入等高级特性,并且提供了强大的异步编程支持。本文将带你了解 Dart 的基础知识,帮助你快速上手。


目录

  1. Dart 简介
  2. 开发环境搭建
  3. 基本语法
  4. 函数
  5. 面向对象编程
  6. 集合类型
  7. 异步编程
  8. 错误与异常处理
  9. Dart 工具与包管理
  10. 示例项目
  11. 附加资源

1. Dart 简介

Dart 是一种面向对象的、类基的编程语言,支持垃圾回收,具有强大的异步编程能力。Dart 的设计目标是提供高性能、可扩展且易于学习的语言,适用于客户端和服务器端开发。它被广泛应用于 Flutter 应用开发中,但也可以用于构建 Web 应用、命令行工具等。

主要特点:

  • 面向对象:支持类、继承、混入等特性。
  • 静态与动态类型:支持可选的类型注解。
  • 异步支持:内置支持异步编程,通过 FutureStream
  • 高性能:通过 AOT 编译和 JIT 编译提供高性能执行。
  • 丰富的标准库:提供了丰富的核心库,涵盖集合、异步、I/O 等功能。

2. 开发环境搭建

要开始学习 Dart,可以选择以下几种开发环境:

2.1 安装 Dart SDK

  1. 下载 Dart SDK

    前往 Dart 官方网站 下载适用于你的操作系统的 Dart SDK。

  2. 安装 Dart SDK

    根据操作系统的不同,按照官网提供的安装指南进行安装。

  3. 配置环境变量

    将 Dart 的 bin 目录添加到系统的环境变量中,以便在命令行中使用 dart 命令。

    示例(macOS/Linux):

    export PATH="$PATH:/path/to/dart-sdk/bin"
    

    示例(Windows):

    dart-sdk\bin 路径添加到系统环境变量的 PATH 中。

  4. 验证安装

    打开终端或命令提示符,运行以下命令检查 Dart 是否安装成功:

    dart --version
    

2.2 使用 IDE

Dart 可以在多种集成开发环境(IDE)中编写和运行,推荐使用以下几种:

  • Visual Studio Code

    • 安装 VS Code 后,通过扩展市场安装 Dart 和 Flutter 插件,提供语法高亮、自动补全、调试等功能。
  • IntelliJ IDEA / Android Studio

    • 安装后,通过插件管理器安装 Dart 插件,支持丰富的开发功能。
  • 其他编辑器

    • 如 Sublime Text、Atom 等也有 Dart 支持的插件,但功能可能不如 VS Code 和 IntelliJ IDEA 丰富。

2.3 使用 DartPad

DartPad 是一个在线的 Dart 编辑器,适合快速尝试和学习 Dart 代码,无需本地安装。


3. 基本语法

3.1 变量与数据类型

Dart 是一种可选类型语言,支持静态类型和动态类型。你可以使用 varfinalconst 来声明变量。

void main() {
  // 静态类型
  int age = 30;
  double height = 5.9;
  String name = 'Alice';
  bool isStudent = false;

  // 动态类型
  var city = 'New York'; // 类型推断为 String
  dynamic anything = 100; // 可以改变类型
  anything = 'Now I am a string';
}
  • var:根据初始化值推断类型,类型一旦确定不能改变。
  • final:声明一个只能赋值一次的变量,运行时常量。
  • const:声明编译时常量,必须在编译时就确定值。
void main() {
  final String language = 'Dart';
  const double pi = 3.14159;
}

3.2 运算符

Dart 支持多种运算符,包括算术运算符、关系运算符、逻辑运算符、赋值运算符等。

void main() {
  int a = 10;
  int b = 3;

  // 算术运算符
  print(a + b); // 13
  print(a - b); // 7
  print(a * b); // 30
  print(a / b); // 3.3333333333333335
  print(a ~/ b); // 3(整除)
  print(a % b); // 1

  // 关系运算符
  print(a > b); // true
  print(a < b); // false
  print(a == b); // false
  print(a != b); // true

  // 逻辑运算符
  bool isAdult = a > 18;
  bool isEmployed = true;
  print(isAdult && isEmployed); // true
  print(isAdult || isEmployed); // true
  print(!isEmployed); // false

  // 赋值运算符
  a += 5; // a = a + 5
  print(a); // 15
}

3.3 控制流

条件语句
void main() {
  int score = 85;

  if (score >= 90) {
    print('A');
  } else if (score >= 80) {
    print('B');
  } else if (score >= 70) {
    print('C');
  } else {
    print('F');
  }
}
switch 语句
void main() {
  String command = 'OPEN';

  switch (command) {
    case 'CLOSED':
      print('The door is closed.');
      break;
    case 'OPEN':
      print('The door is open.');
      break;
    default:
      print('Unknown command.');
  }
}
循环
for 循环
void main() {
  for (int i = 0; i < 5; i++) {
    print('Iteration $i');
  }
}
while 循环
void main() {
  int i = 0;
  while (i < 5) {
    print('Iteration $i');
    i++;
  }
}
do-while 循环
void main() {
  int i = 0;
  do {
    print('Iteration $i');
    i++;
  } while (i < 5);
}
for-in 循环
void main() {
  List<String> fruits = ['Apple', 'Banana', 'Cherry'];

  for (var fruit in fruits) {
    print(fruit);
  }
}

4. 函数

4.1 声明与调用

函数是 Dart 中的基本构建块,用于封装可重用的代码。

void main() {
  sayHello('Alice');
  int sum = add(3, 4);
  print('Sum: $sum');
}

void sayHello(String name) {
  print('Hello, $name!');
}

int add(int a, int b) {
  return a + b;
}

4.2 箭头函数

简化的函数语法,适用于单表达式函数。

int add(int a, int b) => a + b;

void main() {
  print(add(5, 7)); // 12
}

4.3 匿名函数

没有名称的函数,通常用于回调或内联函数。

void main() {
  List<int> numbers = [1, 2, 3, 4, 5];

  numbers.forEach((number) {
    print(number);
  });

  // 使用箭头函数
  numbers.forEach((number) => print(number));
}

5. 面向对象编程

5.1 类与对象

Dart 是一种面向对象的语言,支持类和对象的概念。

class Person {
  String name;
  int age;

  // 构造函数
  Person(this.name, this.age);

  // 方法
  void introduce() {
    print('Hi, my name is $name and I am $age years old.');
  }
}

void main() {
  Person alice = Person('Alice', 30);
  alice.introduce(); // Hi, my name is Alice and I am 30 years old.
}

5.2 继承

Dart 支持类的继承,可以通过 extends 关键字实现。

class Animal {
  void eat() {
    print('Animal is eating.');
  }
}

class Dog extends Animal {
  void bark() {
    print('Dog is barking.');
  }
}

void main() {
  Dog myDog = Dog();
  myDog.eat();  // Animal is eating.
  myDog.bark(); // Dog is barking.
}

5.3 抽象类与接口

抽象类

抽象类不能被实例化,用于定义子类必须实现的方法。

abstract class Shape {
  double area();
}

class Circle extends Shape {
  double radius;

  Circle(this.radius);

  @override
  double area() => 3.14159 * radius * radius;
}

void main() {
  Circle circle = Circle(5);
  print('Area: ${circle.area()}'); // Area: 78.53975
}
接口

Dart 中的每个类都隐式地定义了一个接口。可以通过 implements 关键字实现接口。

class Animal {
  void eat() {
    print('Animal is eating.');
  }
}

class Bird implements Animal {
  @override
  void eat() {
    print('Bird is eating.');
  }

  void fly() {
    print('Bird is flying.');
  }
}

void main() {
  Bird sparrow = Bird();
  sparrow.eat(); // Bird is eating.
  sparrow.fly(); // Bird is flying.
}

6. 集合类型

6.1 List

Dart 中的 List 是有序的可变集合,可以存储多个元素。

void main() {
  List<int> numbers = [1, 2, 3, 4, 5];
  print(numbers); // [1, 2, 3, 4, 5]

  // 添加元素
  numbers.add(6);
  print(numbers); // [1, 2, 3, 4, 5, 6]

  // 访问元素
  print(numbers[0]); // 1

  // 遍历
  for (var number in numbers) {
    print(number);
  }
}

6.2 Set

Set 是无序且唯一的集合,不能包含重复的元素。

void main() {
  Set<String> fruits = {'Apple', 'Banana', 'Cherry'};
  print(fruits); // {Apple, Banana, Cherry}

  // 添加元素
  fruits.add('Date');
  print(fruits); // {Apple, Banana, Cherry, Date}

  // 尝试添加重复元素
  fruits.add('Apple');
  print(fruits); // {Apple, Banana, Cherry, Date}

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

6.3 Map

Map 是键值对的集合,每个键都是唯一的。

void main() {
  Map<String, int> ages = {
    'Alice': 30,
    'Bob': 25,
    'Charlie': 35,
  };
  print(ages); // {Alice: 30, Bob: 25, Charlie: 35}

  // 添加或更新元素
  ages['David'] = 40;
  print(ages); // {Alice: 30, Bob: 25, Charlie: 35, David: 40}

  // 访问元素
  print(ages['Alice']); // 30

  // 遍历
  ages.forEach((key, value) {
    print('$key is $value years old.');
  });
}

7. 异步编程

Dart 提供了强大的异步编程支持,主要通过 FutureStream 实现。

7.1 Future

Future 表示一个可能在将来某个时刻完成并返回结果的操作。

Future<String> fetchData() async {
  await Future.delayed(Duration(seconds: 2));
  return 'Data fetched';
}

void main() async {
  print('Fetching data...');
  String data = await fetchData();
  print(data); // Data fetched
}

7.2 async & await

asyncawait 关键字用于编写异步代码,使其看起来更像同步代码。

Future<void> printData() async {
  String data = await fetchData();
  print(data);
}

void main() async {
  await printData();
}

7.3 Stream

Stream 是一个异步数据序列,可以逐个地处理事件。

Stream<int> countStream(int max) async* {
  for (int i = 1; i <= max; i++) {
    await Future.delayed(Duration(seconds: 1));
    yield i;
  }
}

void main() async {
  await for (var value in countStream(5)) {
    print(value); // 1, 2, 3, 4, 5 每秒打印一个
  }
}

8. 错误与异常处理

Dart 提供了异常处理机制,通过 try-catch 块捕获和处理异常。

void main() {
  try {
    int result = divide(10, 0);
    print(result);
  } catch (e) {
    print('Error: $e');
  } finally {
    print('This is always executed.');
  }
}

int divide(int a, int b) {
  if (b == 0) {
    throw Exception('Division by zero');
  }
  return a ~/ b;
}
  • try:包裹可能抛出异常的代码。
  • catch:捕获并处理异常。
  • finally:无论是否发生异常,都会执行的代码块。

自定义异常

可以定义自定义异常类,以便更好地处理特定的错误情况。

class NegativeNumberException implements Exception {
  String cause;
  NegativeNumberException(this.cause);
}

int sqrt(int x) {
  if (x < 0) {
    throw NegativeNumberException('Cannot calculate square root of negative number');
  }
  return x; // 这里只是示例,实际应该计算平方根
}

void main() {
  try {
    sqrt(-4);
  } catch (e) {
    if (e is NegativeNumberException) {
      print('Custom Exception: ${e.cause}');
    } else {
      print('Unknown Exception: $e');
    }
  }
}

9. Dart 工具与包管理

9.1 Pub

pub 是 Dart 的包管理工具,用于管理项目的依赖、发布包等。常用命令包括:

  • 添加依赖

    pubspec.yaml 中添加依赖,然后运行:

    dart pub get
    
  • 升级依赖

    dart pub upgrade
    
  • 发布包

    参考 pub.dev 发布指南

9.2 常用包

  • http:用于发送 HTTP 请求。
  • json_serializable:自动生成 JSON 解析代码。
  • provider:状态管理解决方案。
  • sqflite:SQLite 数据库支持。
  • path:文件路径处理。

示例:使用 http 包发送请求

import 'package:http/http.dart' as http;

Future<void> fetchData() async {
  var url = Uri.parse('https://jsonplaceholder.typicode.com/posts/1');
  var response = await http.get(url);
  if (response.statusCode == 200) {
    print('Response data: ${response.body}');
  } else {
    print('Request failed with status: ${response.statusCode}.');
  }
}

10. 示例项目

通过一个简单的示例项目,综合运用所学知识。

示例项目:待办事项应用

  1. 创建项目

    dart create todo_app
    cd todo_app
    
  2. 编辑 pubspec.yaml

    添加依赖:

    dependencies:
      http: ^0.13.4
      provider: ^6.0.0
    
  3. 实现核心功能

    • 定义模型

      class Todo {
        final int id;
        final String title;
        bool completed;
      
        Todo({
          required this.id,
          required this.title,
          this.completed = false,
        });
      }
      
    • 创建 Provider

      import 'package:flutter/foundation.dart';
      import 'todo.dart';
      
      class TodoProvider with ChangeNotifier {
        List<Todo> _todos = [];
      
        List<Todo> get todos => _todos;
      
        void addTodo(Todo todo) {
          _todos.add(todo);
          notifyListeners();
        }
      
        void toggleTodoStatus(int id) {
          var todo = _todos.firstWhere((todo) => todo.id == id);
          todo.completed = !todo.completed;
          notifyListeners();
        }
      }
      
    • 构建 UI

      import 'package:flutter/material.dart';
      import 'package:provider/provider.dart';
      import 'todo_provider.dart';
      import 'todo.dart';
      
      void main() {
        runApp(
          ChangeNotifierProvider(
            create: (context) => TodoProvider(),
            child: MyApp(),
          ),
        );
      }
      
      class MyApp extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
            title: 'Todo App',
            home: TodoPage(),
          );
        }
      }
      
      class TodoPage extends StatelessWidget {
        final TextEditingController _controller = TextEditingController();
      
        @override
        Widget build(BuildContext context) {
          var todoProvider = Provider.of<TodoProvider>(context);
      
          return Scaffold(
            appBar: AppBar(title: Text('Todo List')),
            body: Column(
              children: [
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Row(
                    children: [
                      Expanded(
                        child: TextField(
                          controller: _controller,
                          decoration: InputDecoration(labelText: 'Enter todo'),
                        ),
                      ),
                      IconButton(
                        icon: Icon(Icons.add),
                        onPressed: () {
                          if (_controller.text.isNotEmpty) {
                            todoProvider.addTodo(Todo(
                              id: DateTime.now().millisecondsSinceEpoch,
                              title: _controller.text,
                            ));
                            _controller.clear();
                          }
                        },
                      )
                    ],
                  ),
                ),
                Expanded(
                  child: ListView.builder(
                    itemCount: todoProvider.todos.length,
                    itemBuilder: (context, index) {
                      var todo = todoProvider.todos[index];
                      return ListTile(
                        title: Text(todo.title),
                        trailing: Checkbox(
                          value: todo.completed,
                          onChanged: (value) {
                            todoProvider.toggleTodoStatus(todo.id);
                          },
                        ),
                      );
                    },
                  ),
                )
              ],
            ),
          );
        }
      }
      
  4. 运行项目

    dart run
    

11. 学习参考资源