跳到主要内容

Dart 语言基础

Dart 是 Flutter 的核心语言,本章将介绍 Dart 语言的基础语法和核心概念。

变量和数据类型

变量声明

Dart 提供了多种变量声明方式:

// 使用 var 自动推断类型
var name = '张三';
var age = 25;

// 显式声明类型
String city = '北京';
int score = 95;

// 使用 final 声明不可变变量(运行时确定值)
final currentTime = DateTime.now();

// 使用 const 声明编译时常量
const pi = 3.14159;
const maxRetry = 3;

final 和 const 的区别

  • final:变量只能被赋值一次,值在运行时确定
  • const:编译时常量,值在编译时就必须确定
final name = '张三';  // 正确
// name = '李四'; // 错误!final 变量不能重新赋值

const pi = 3.14; // 正确
// const now = DateTime.now(); // 错误!const 必须是编译时常量

内置数据类型

数值类型

// 整数
int age = 25;
int hexValue = 0xFF; // 十六进制
int bigNumber = 1000000000000000000;

// 浮点数
double price = 19.99;
double scientific = 2.5e5; // 250000.0

// num 可以存储整数或浮点数
num value = 10;
value = 10.5; // 可以赋值为浮点数

字符串

// 单引号和双引号
String name1 = '张三';
String name2 = "李四";

// 多行字符串
String poem = '''
静夜思
床前明月光,
疑是地上霜。
''';

// 字符串插值
String greeting = '你好,$name1!';
String calculation = '2 + 3 = ${2 + 3}';

// 原始字符串(不处理转义字符)
String path = r'C:\Users\Admin\Documents';

// 常用字符串方法
String text = 'Hello, Dart!';
print(text.length); // 12
print(text.toUpperCase()); // HELLO, DART!
print(text.toLowerCase()); // hello, dart!
print(text.contains('Dart')); // true
print(text.substring(0, 5)); // Hello
print(text.split(',')); // [Hello, Dart!]

布尔类型

bool isActive = true;
bool isDeleted = false;

// 布尔运算
bool result = (5 > 3) && (10 < 20); // true

列表(List)

// 创建列表
List<int> numbers = [1, 2, 3, 4, 5];
var names = ['张三', '李四', '王五'];

// 不可变列表
const colors = ['red', 'green', 'blue'];

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

// 添加元素
numbers.add(6);
numbers.addAll([7, 8]);

// 插入元素
numbers.insert(0, 0);

// 删除元素
numbers.remove(3);
numbers.removeAt(0);

// 其他常用方法
print(numbers.length); // 长度
print(numbers.contains(5)); // 是否包含
print(numbers.indexOf(3)); // 查找索引
print(numbers.sublist(0, 3)); // 子列表

// 遍历列表
for (var num in numbers) {
print(num);
}

numbers.forEach((num) => print(num));

// 映射和过滤
var squared = numbers.map((n) => n * n).toList();
var evens = numbers.where((n) => n % 2 == 0).toList();

集合(Set)

// 创建集合(不包含重复元素)
Set<String> fruits = {'苹果', '香蕉', '橙子'};

// 添加元素
fruits.add('葡萄');
fruits.addAll(['苹果', '西瓜']); // '苹果'不会重复添加

// 删除元素
fruits.remove('香蕉');

// 集合运算
Set<int> set1 = {1, 2, 3, 4};
Set<int> set2 = {3, 4, 5, 6};

print(set1.union(set2)); // {1, 2, 3, 4, 5, 6} 并集
print(set1.intersection(set2)); // {3, 4} 交集
print(set1.difference(set2)); // {1, 2} 差集

映射(Map)

// 创建映射
Map<String, int> scores = {
'张三': 90,
'李四': 85,
'王五': 95,
};

// 访问元素
print(scores['张三']); // 90

// 添加或修改元素
scores['赵六'] = 88;
scores['张三'] = 92; // 修改已存在的键

// 删除元素
scores.remove('李四');

// 检查键和值
print(scores.containsKey('张三')); // true
print(scores.containsValue(95)); // true

// 获取所有键和值
print(scores.keys); // (张三, 王五, 赵六)
print(scores.values); // (92, 95, 88)

// 遍历 Map
scores.forEach((name, score) {
print('$name: $score');
});

运算符

算术运算符

int a = 10, b = 3;

print(a + b); // 13 加法
print(a - b); // 7 减法
print(a * b); // 30 乘法
print(a / b); // 3.333... 除法
print(a ~/ b); // 3 整除
print(a % b); // 1 取余

比较运算符

print(5 == 5);   // true  等于
print(5 != 3); // true 不等于
print(5 > 3); // true 大于
print(5 < 3); // false 小于
print(5 >= 5); // true 大于等于
print(5 <= 3); // false 小于等于

逻辑运算符

bool a = true, b = false;

print(a && b); // false 逻辑与
print(a || b); // true 逻辑或
print(!a); // false 逻辑非

条件运算符

// 三元运算符
String result = (5 > 3) ? '正确' : '错误';

// 空值合并运算符
String name = null;
String displayName = name ?? '匿名用户'; // 如果 name 为 null,使用默认值

// 空值感知运算符
String? nullableName;
print(nullableName?.length); // 如果为 null,返回 null 而不是报错

控制流

条件语句

// if-else
int score = 85;

if (score >= 90) {
print('优秀');
} else if (score >= 80) {
print('良好');
} else if (score >= 60) {
print('及格');
} else {
print('不及格');
}

// switch-case
String grade = 'A';

switch (grade) {
case 'A':
print('优秀');
break;
case 'B':
print('良好');
break;
case 'C':
print('及格');
break;
default:
print('不及格');
}

循环语句

// for 循环
for (int i = 0; i < 5; i++) {
print(i);
}

// for-in 循环
var fruits = ['苹果', '香蕉', '橙子'];
for (var fruit in fruits) {
print(fruit);
}

// while 循环
int count = 0;
while (count < 5) {
print(count);
count++;
}

// do-while 循环
int num = 0;
do {
print(num);
num++;
} while (num < 5);

// break 和 continue
for (int i = 0; i < 10; i++) {
if (i == 3) continue; // 跳过当前迭代
if (i == 7) break; // 退出循环
print(i); // 输出: 0, 1, 2, 4, 5, 6
}

函数

基本语法

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

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

// 可选参数
String greet(String name, [String greeting = '你好']) {
return '$greeting,$name!';
}

print(greet('张三')); // 你好,张三!
print(greet('李四', '欢迎')); // 欢迎,李四!

// 命名参数
void printUser({required String name, int age = 18, String? city}) {
print('姓名:$name,年龄:$age,城市:${city ?? "未知"}');
}

printUser(name: '张三', age: 25, city: '北京');
printUser(name: '李四'); // 使用默认值

// 函数作为参数
void forEach(List<int> list, void Function(int) action) {
for (var item in list) {
action(item);
}
}

forEach([1, 2, 3], (n) => print(n));

// 匿名函数
var square = (int x) => x * x;
print(square(5)); // 25

闭包

// 闭包示例
Function makeCounter() {
int count = 0;
return () {
count++;
return count;
};
}

var counter = makeCounter();
print(counter()); // 1
print(counter()); // 2
print(counter()); // 3

类和面向对象

定义类

class Person {
// 实例变量
String name;
int age;

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

// 命名构造函数
Person.guest() : name = '访客', age = 0;

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

// 重写 toString
@override
String toString() => 'Person(name: $name, age: $age)';
}

// 使用类
var person = Person('张三', 25);
person.sayHello();
print(person);

var guest = Person.guest();
print(guest);

继承

class Animal {
String name;

Animal(this.name);

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

class Dog extends Animal {
String breed;

Dog(String name, this.breed) : super(name);

@override
void speak() {
print('$name 汪汪叫');
}

void fetch() {
print('$name 正在捡球');
}
}

var dog = Dog('旺财', '金毛');
dog.speak(); // 旺财 汪汪叫
dog.fetch(); // 旺财正在捡球

抽象类和接口

// 抽象类
abstract class Shape {
double get area;
double get perimeter;

void describe() {
print('面积:$area,周长:$perimeter');
}
}

// 实现抽象类
class Circle extends Shape {
double radius;

Circle(this.radius);

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

@override
double get perimeter => 2 * 3.14159 * radius;
}

class Rectangle extends Shape {
double width, height;

Rectangle(this.width, this.height);

@override
double get area => width * height;

@override
double get perimeter => 2 * (width + height);
}

// 使用
var circle = Circle(5);
circle.describe();

var rect = Rectangle(4, 6);
rect.describe();

Mixin

Mixin 用于在多个类层次结构中复用代码:

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

mixin Flyable {
void fly() {
print('正在飞行');
}
}

class Duck extends Animal with Swimmable, Flyable {
Duck(String name) : super(name);
}

var duck = Duck('唐老鸭');
duck.swim(); // 正在游泳
duck.fly(); // 正在飞行

Getter 和 Setter

class Temperature {
double _celsius; // 私有变量(以 _ 开头)

Temperature(this._celsius);

// Getter
double get fahrenheit => _celsius * 9 / 5 + 32;

// Setter
set fahrenheit(double value) {
_celsius = (value - 32) * 5 / 9;
}

double get celsius => _celsius;
set celsius(double value) => _celsius = value;
}

var temp = Temperature(100);
print(temp.fahrenheit); // 212.0
temp.fahrenheit = 32;
print(temp.celsius); // 0.0

异步编程

Future

Future 表示一个异步操作的结果:

// 模拟异步操作
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 2));
return '获取的数据';
}

// 使用 async/await
void getData() async {
print('开始获取数据...');
String data = await fetchData();
print('获取到:$data');
}

// 使用 then
fetchData().then((data) {
print('获取到:$data');
}).catchError((error) {
print('错误:$error');
});

// Future 链式调用
fetchData()
.then((data) => data.toUpperCase())
.then((upper) => print(upper))
.catchError((error) => print(error));

Stream

Stream 表示一系列异步事件:

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

// 使用 Stream
void listenToStream() async {
await for (var count in countStream()) {
print(count);
}
}

// Stream 方法
countStream()
.where((n) => n % 2 == 0) // 过滤
.map((n) => n * n) // 映射
.listen((n) => print(n)); // 监听

异常处理

// 抛出异常
void validateAge(int age) {
if (age < 0) {
throw FormatException('年龄不能为负数');
}
if (age > 150) {
throw Exception('年龄不合理');
}
}

// 捕获异常
try {
validateAge(-5);
} on FormatException catch (e) {
print('格式错误:$e');
} on Exception catch (e) {
print('异常:$e');
} catch (e) {
print('未知错误:$e');
} finally {
print('清理工作');
}

泛型

// 泛型类
class Cache<T> {
final Map<String, T> _cache = {};

T? get(String key) => _cache[key];

void set(String key, T value) {
_cache[key] = value;
}
}

// 使用泛型
var stringCache = Cache<String>();
stringCache.set('name', '张三');
print(stringCache.get('name'));

var intCache = Cache<int>();
intCache.set('age', 25);

// 泛型函数
T first<T>(List<T> list) {
if (list.isEmpty) throw Exception('列表为空');
return list.first;
}

print(first([1, 2, 3])); // 1
print(first(['a', 'b', 'c'])); // a

枚举

// 基本枚举
enum Color { red, green, blue }

// 带属性的枚举(Dart 3.0+)
enum Status {
active('激活'),
inactive('未激活'),
pending('待处理');

final String description;
const Status(this.description);
}

// 使用枚举
Color color = Color.red;
print(color); // Color.red
print(color.index); // 0
print(Color.values); // [Color.red, Color.green, Color.blue]

Status status = Status.active;
print(status.description); // 激活

// switch 使用枚举
switch (status) {
case Status.active:
print('账户已激活');
break;
case Status.inactive:
print('账户未激活');
break;
case Status.pending:
print('账户待处理');
break;
}

小结

本章我们学习了:

  1. 变量和数据类型:var、final、const、数值、字符串、布尔、List、Set、Map
  2. 运算符:算术、比较、逻辑、条件运算符
  3. 控制流:if-else、switch、for、while 循环
  4. 函数:参数类型、箭头函数、闭包
  5. 面向对象:类、继承、抽象类、Mixin
  6. 异步编程:Future、async/await、Stream
  7. 异常处理:try-catch-finally
  8. 泛型和枚举

练习

  1. 创建一个 Student 类,包含姓名、成绩属性,实现成绩等级判定
  2. 使用 Future 模拟网络请求,获取并处理数据
  3. 实现一个简单的缓存类,支持泛型
  4. 使用 Stream 实现一个倒计时功能

下一步

掌握 Dart 基础后,下一章我们将学习 Widget 基础,开始构建 Flutter 界面。