🚀 Dart基础从入门到精通:变量、函数、异步、类全解析(2026最新版)

🔥 保姆级教学:通过可运行代码+通俗解释,帮你彻底掌握Dart核心语法,零基础也能轻松入门!

引言:为什么要学Dart?

Dart是Google推出的现代化编程语言,不仅是Flutter跨平台开发的官方语言,还可用于后端开发、CLI工具编写等场景。它兼具静态类型安全和动态语言的灵活性,语法简洁易上手,是2026年开发者必备技能之一。

本文将从变量、函数、异步、类四大核心模块入手,结合大量可直接运行的代码实例,帮你快速构建Dart知识体系。每个知识点都配有运行结果和实战建议,确保你能边学边练,真正做到“从理论到实战”的无缝衔接。

在这里插入图片描述

一、变量:程序的“数据容器”

变量是存储数据的基本单元,Dart的变量系统兼具强类型特性和灵活的类型推断能力,新手需重点理解以下核心概念:

1. 变量声明:var、final、const的区别

Dart支持类型自动推断,也可显式指定变量类型。核心关键字的区别如下:

关键字 特点 适用场景
var 可重新赋值,类型自动推断 临时变量、类型明确的业务场景
final 不可重新赋值,运行时确定值 初始化后无需修改的变量(如用户ID、设备编号)
const 编译时常量,不可变且值需为字面量 固定常量(如数学常量、配置参数)

代码实例

void main() {
  // 1. var:类型推断为String,支持重新赋值
  var name = "小明"; 
  name = "小红"; // ✅ 合法:var变量可重新赋值
  print(name); // 输出:小红

  // 2. final:运行时确定值,不可重新赋值
  final age = 18; 
  // age = 20; ❌ 编译错误:final变量赋值后不可修改

  // 3. const:编译时常量,值必须是字面量或常量表达式
  const pi = 3.14159; 
  const circleArea = pi * 5 * 5; // 编译时直接计算结果
  print(circleArea); // 输出:78.53975
}

2. 类型系统:强类型与空安全

Dart 2.12+ 引入空安全(Null Safety) 特性,默认禁止变量赋值为null,需显式声明可空类型:

void main() {
  // 非空类型(默认):禁止赋值为null
  String name = "张三"; 
  // name = null; ❌ 编译错误:非空类型不能赋值为null

  // 可空类型(变量类型后加?):允许赋值为null
  String? nullableName = null; 
  nullableName = "李四"; // ✅ 合法:可空类型支持null赋值

  // late关键字:延迟初始化(非空类型但暂时不赋值)
  late String delayedName; 
  delayedName = "王五"; // ✅ 后续赋值合法
}

3. 常用数据类型

Dart基础数据类型与主流语言类似,但有细节需注意:

void main() {
  // 数值类型:int(整数)、double(浮点数),支持自动类型提升
  int a = 10;
  double b = 3.14;
  print(a + b); // 输出:13.14(int自动转为double)

  // 布尔类型:仅true/false,无“非0即真”规则
  bool isTrue = true;
  if (isTrue) print("条件成立"); // 输出:条件成立

  // 字符串:单引号、双引号、多行字符串
  String str1 = '单引号';
  String str2 = "双引号";
  String str3 = '''多行
字符串''';
  print(str1 + str2); // 输出:单引号双引号
  print("a的值是${a}"); // 插值表达式:输出a的值是10

  // 列表(数组):泛型指定元素类型,支持动态增删
  List<int> numbers = [1, 2, 3];
  numbers.add(4);
  print(numbers); // 输出:[1, 2, 3, 4]

  // 映射(字典):键值对结构,泛型指定键值类型
  Map<String, dynamic> person = {
    "name": "小明",
    "age": 18
  };
  print(person["name"]); // 输出:小明
}

二、函数:程序的“功能模块”

函数是实现特定功能的代码块,Dart的函数支持多种参数形式高阶函数,灵活性极强。

1. 函数定义与调用

基础语法:返回类型 函数名(参数列表) { 函数体 }(无返回值时void可省略)

// 无返回值函数(void可省略)
void printHello() {
  print("Hello Dart!");
}

// 有返回值函数:显式指定返回类型为int
int add(int a, int b) {
  return a + b;
}

void main() {
  printHello(); // 调用无返回值函数:输出Hello Dart!
  int result = add(2, 3);
  print(result); // 输出:5
}

2. 参数类型:位置参数、命名参数、可选参数

Dart的参数设计灵活,可满足不同业务场景的参数传递需求:

// 1. 位置参数(必传):按顺序传递,缺一不可
void sayHi(String name, int age) {
  print("Hi $name, you are $age years old.");
}

// 2. 命名参数(用{}包裹,可选):传参时指定参数名,可设置默认值
void sayHello({String? name, int age = 18}) { 
  print("Hello ${name ?? 'Guest'}, age $age");
}

// 3. 可选位置参数(用[]包裹):按位置可选传递
void sayGreeting(String message, [String? name]) {
  print("$message ${name ?? 'everyone'}");
}

void main() {
  sayHi("小明", 18); // 输出:Hi 小明, you are 18 years old.
  
  sayHello(name: "小红"); // 输出:Hello 小红, age 18(age使用默认值)
  sayHello(age: 20); // 输出:Hello Guest, age 20(name为null)
  
  sayGreeting("Hi"); // 输出:Hi everyone
  sayGreeting("Hi", "小张"); // 输出:Hi 小张
}

3. 箭头函数与匿名函数

简化代码的利器,适合简短逻辑或回调场景:

void main() {
  // 箭头函数(单行逻辑):简化函数体,自动返回表达式结果
  int multiply(int a, int b) => a * b;
  print(multiply(3, 4)); // 输出:12

  // 匿名函数(无函数名):常用于集合遍历、回调函数
  List<int> numbers = [1, 2, 3];
  numbers.forEach((num) => print(num * 2)); // 输出:2、4、6

  // 闭包:函数捕获外部变量,即使外部作用域销毁仍可访问
  Function makeAdder(int addBy) {
    return (int i) => i + addBy;
  }
  var add5 = makeAdder(5);
  print(add5(3)); // 输出:8(捕获了外部变量addBy=5)
}

三、异步编程:Future与async/await

Dart的异步模型基于单线程事件循环,通过Futureasync/await处理异步操作(如网络请求、文件读写),避免阻塞主线程。

1. Future:异步操作的“承诺”

Future代表一个“未来可能完成的操作”,类比“快递包裹”——下单后无需等待,包裹送达后再处理:

void main() {
  // 模拟网络请求(返回Future<String>)
  Future<String> fetchData() {
    return Future.delayed(Duration(seconds: 2), () {
      return "网络请求结果"; // 2秒后返回数据
    });
  }

  // 处理Future的方式1:then/catchError 链式调用
  fetchData().then((data) {
    print("成功:$data"); // 异步操作成功时执行
  }).catchError((error) {
    print("失败:$error"); // 异步操作失败时执行
  }).whenComplete(() {
    print("操作完成"); // 无论成功/失败都会执行
  });

  print("主线程继续执行"); // 先输出这句话,异步操作不阻塞主线程
}

运行结果

主线程继续执行
(等待2秒后)
成功:网络请求结果
操作完成

2. async/await:异步代码同步化

async/awaitFuture的语法糖,让异步代码看起来像同步代码,可读性更高:

void main() async { // 主函数标记为async(Dart 2.14+支持main函数async)
  print("开始请求");
  
  try {
    String data = await fetchData(); // 等待Future完成,获取结果
    print("成功:$data");
  } catch (error) {
    print("失败:$error"); // 捕获异步操作异常
  } finally {
    print("操作完成"); // 无论成功/失败都会执行
  }

  print("请求结束");
}

// 复用上面的fetchData函数
Future<String> fetchData() {
  return Future.delayed(Duration(seconds: 2), () => "网络请求结果");
}

运行结果

开始请求
(等待2秒后)
成功:网络请求结果
操作完成
请求结束

3. 并发执行:Future.wait

同时执行多个异步操作,等待所有操作完成后统一处理结果(总耗时为最长的异步操作耗时):

void main() async {
  // 模拟两个异步请求
  Future<String> fetchUser() => Future.delayed(Duration(seconds: 1), () => "用户信息");
  Future<String> fetchOrders() => Future.delayed(Duration(seconds: 2), () => "订单信息");

  // 并发执行,总耗时2秒(而非1+2=3秒)
  List<String> results = await Future.wait([fetchUser(), fetchOrders()]);
  print(results); // 输出:[用户信息, 订单信息]
}

四、类:面向对象的核心

Dart是纯面向对象语言(一切皆对象),类是组织代码的基本单元,支持封装、继承、多态等核心特性。

1. 类的定义与构造函数

// 定义Person类:封装姓名、年龄属性和打招呼方法
class Person {
  String name;
  int age;

  // 1. 默认构造函数(语法糖):直接初始化成员变量
  Person(this.name, this.age);

  // 2. 命名构造函数:支持多个构造函数,满足不同初始化场景
  Person.fromBirthYear(String name, int birthYear) {
    this.name = name;
    this.age = DateTime.now().year - birthYear;
  }

  // 3. 工厂构造函数:返回实例,常用于单例模式
  static final Person _instance = Person("单例", 0);
  factory Person.singleton() => _instance;

  // 类方法:封装行为
  void sayHello() {
    print("Hello, I'm $name, $age years old.");
  }
}

void main() {
  // 使用默认构造函数
  Person p1 = Person("小明", 18);
  p1.sayHello(); // 输出:Hello, I'm 小明, 18 years old.

  // 使用命名构造函数(按出生年份计算年龄)
  Person p2 = Person.fromBirthYear("小红", 2000);
  p2.sayHello(); // 输出:Hello, I'm 小红, 26 years old.(2026-2000)

  // 使用工厂构造函数(单例:多次调用返回同一个实例)
  Person p3 = Person.singleton();
  Person p4 = Person.singleton();
  print(p3 == p4); // 输出:true
}

2. 继承与多态

Dart支持单继承,子类通过extends关键字继承父类,可重写父类方法实现多态:

// 子类Student继承父类Person
class Student extends Person {
  String school; // 子类新增属性

  // 子类构造函数:必须通过super调用父类构造函数
  Student(String name, int age, this.school) : super(name, age);

  // 重写父类方法:@override注解标识
  
  void sayHello() {
    super.sayHello(); // 调用父类原方法
    print("I study at $school."); // 子类扩展逻辑
  }
}

void main() {
  Student s = Student("小李", 20, "清华大学");
  s.sayHello();
}

运行结果

Hello, I'm 小李, 20 years old.
I study at 清华大学.

3. 混入(Mixin):代码复用的黑科技

Mixin是Dart特有的代码复用方式,允许一个类“混入”多个类的方法(无需继承),解决单继承的局限性:

// 定义Mixin(用mixin关键字,不能实例化)
mixin Runnable {
  void run() {
    print("正在跑步");
  }
}

mixin Swimmable {
  void swim() {
    print("正在游泳");
  }
}

// 类混入多个Mixin:with关键字
class Athlete extends Person with Runnable, Swimmable {
  Athlete(String name, int age) : super(name, age);
}

void main() {
  Athlete a = Athlete("运动员", 25);
  a.run(); // 输出:正在跑步(来自Runnable)
  a.swim(); // 输出:正在游泳(来自Swimmable)
  a.sayHello(); // 输出:Hello, I'm 运动员, 25 years old.(来自Person)
}

4. 接口与抽象类

  • 抽象类:用abstract修饰,不能实例化,用于定义规范(可包含抽象方法和具体方法)。
  • 接口:Dart中每个类都可作为接口,用implements实现(需重写所有属性和方法)。
// 抽象类:定义动物的通用规范
abstract class Animal {
  void eat(); // 抽象方法(无实现,子类必须重写)
  
  void sleep() { // 具体方法(有实现,子类可复用)
    print("睡觉");
  }
}

// 继承抽象类:重写抽象方法
class Dog extends Animal {
  
  void eat() {
    print("狗吃骨头");
  }
}

// 实现接口(多个接口):需重写所有方法和属性
class Bird implements Animal, Runnable {
  
  void eat() {
    print("鸟吃虫子");
  }

  
  void sleep() {
    print("鸟站在树枝上睡觉");
  }

  
  void run() {
    print("鸟快速跑");
  }
}

void main() {
  Dog dog = Dog();
  dog.eat(); // 输出:狗吃骨头
  dog.sleep(); // 输出:睡觉

  Bird bird = Bird();
  bird.eat(); // 输出:鸟吃虫子
  bird.run(); // 输出:鸟快速跑
}

五、实战:Dart基础综合案例

通过学生管理系统综合运用以上知识点,实现“加载学生数据→添加学生→展示学生信息”的完整流程:

// 1. 定义顶层Person类
class Person {
  String name;
  int age;
  Person(this.name, this.age);
  void sayHello() => print("我是$name,今年$age岁");
}

void main() async {
  // 2. 定义学生列表(泛型约束为Student)
  List<Student> students = [];

  // 3. 函数:添加学生到列表
  void addStudent(Student student) {
    students.add(student);
    print("添加学生:${student.name}");
  }

  // 4. 异步函数:模拟从服务器加载学生数据
  Future<List<Student>> fetchStudents() async {
    await Future.delayed(Duration(seconds: 1)); // 模拟网络延迟
    return [
      Student("小明", 18, "高一(1)班"),
      Student("小红", 17, "高一(2)班")
    ];
  }

  // 5. 定义Student子类(继承Person)
  class Student extends Person {
    String className;
    Student(String name, int age, this.className) : super(name, age);
    
    
    void sayHello() {
      print("我是$className$name,今年$age岁");
    }
  }

  // 执行流程
  print("开始加载学生数据...");
  List<Student> fetchedStudents = await fetchStudents();
  fetchedStudents.forEach(addStudent);
  
  print("\n学生列表:");
  students.forEach((s) => s.sayHello());
}

运行结果

开始加载学生数据...
(等待1秒后)
添加学生:小明
添加学生:小红

学生列表:
我是高一(1)班的小明,今年18岁
我是高一(2)班的小红,今年17岁

六、总结与学习建议

核心要点回顾

  1. 变量:掌握var/final/const的区别,理解空安全的核心逻辑;
  2. 函数:灵活运用位置参数、命名参数,熟悉箭头函数和闭包;
  3. 异步:用Future处理异步操作,async/await简化异步代码;
  4. :掌握构造函数、继承、Mixin、抽象类/接口的使用场景。

学习建议

  1. 多写代码:每个知识点至少写3个不同的例子,加深理解;
  2. 调试代码:用print或IDE调试工具查看变量变化,理解执行流程;
  3. 官方文档:优先阅读Dart官网(dart.dev),获取最新语法和最佳实践;
  4. 项目实践:用Dart写小项目(如TodoList、计算器),将知识点落地。

常见误区

  1. 混淆finalconstconst是编译时常量,final是运行时常量;
  2. 忘记async修饰函数:使用await的函数必须标记为async
  3. 继承与接口混淆:extends是继承(复用代码),implements是实现接口(遵守规范);
  4. 空安全使用不当:非空类型直接赋值null,或可空类型未做判空处理。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐