在掌握了 Dart 的基本语法后,我们将深入学习构建复杂应用的三个核心基石:函数 (Functions)、类 (Classes) 和异步编程 (Asynchronous Programming)。这部分内容对于理解 Flutter 的 Widget 结构和处理网络请求等耗时操作至关重要。
学习目标
- 掌握如何定义和使用函数,包括各类参数。
- 理解面向对象编程,学会创建和使用类 (Class)。
- 初步掌握 Dart 的异步处理方式:
Future
,async
, 和await
。
1. 函数 (Functions)
函数是一段可重复使用的代码块。在 Dart 中,即使是函数也是对象,类型为 Function
。
基础函数定义
一个最简单的函数包含一个返回值类型、一个函数名、一对括号 ()
和一个函数体 {}
。
dart
// 返回值类型为 String,函数名为 greet,接收一个 String 类型的参数 name
String greet(String name) {
return 'Hello, $name!';
}
void main() {
// 调用函数
var message = greet('Tom');
print(message); // 输出: Hello, Tom!
}
提示 :如果函数不返回任何值,使用
void
作为返回类型。main()
函数就是一个典型的例子。
箭头函数 (Arrow Functions)
如果函数体只包含一个表达式,你可以使用更简洁的箭头语法 =>
。
dart
// 上面的 greet 函数可以简写为:
String greet(String name) => 'Hello, $name!';
void main() {
print(greet('Jerry')); // 输出: Hello, Jerry!
}
函数参数
Dart 提供了非常灵活的参数类型,这在构造 Flutter Widget 时极其常用。
a) 可选的位置参数 []
用 []
包裹的参数是可选的。
dart
String say(String from, String msg, [String? device]) {
var result = '$from says $msg';
// 如果 device 不为 null,则将其拼接到结果中
if (device != null) {
result = '$result on a $device';
}
return result;
}
void main() {
print(say('John', 'Hello')); // 输出: John says Hello
print(say('Jane', 'Hi', 'iPhone')); // 输出: Jane says Hi on a iPhone
}
b) 可选的命名参数 {}
(Flutter 中最常用)
用 {}
包裹的参数是可选的命名参数。调用时必须指定参数名,这让代码可读性变得非常高。
dart
// enable 和 port 都是可选的命名参数
void setup({bool enable = false, int port = 8080}) {
print('Setup complete. Enable: $enable, Port: $port');
}
void main() {
setup(); // 使用默认值。输出: Setup complete. Enable: false, Port: 8080
setup(enable: true); // 指定 enable 参数。输出: Setup complete. Enable: true, Port: 8080
setup(port: 9000, enable: true); // 指定所有参数,顺序无关。输出: Setup complete. Enable: true, Port: 9000
}
在 Flutter 中,几乎所有 Widget 的构造函数都使用了命名参数,例如
Text('Hi', style: TextStyle(color: Colors.red))
。
2. 类 (Classes)
类是创建对象的蓝图。在 Flutter 中,你看到的每一个界面元素,比如 Text
, Button
, Container
,本质上都是一个类。
定义一个类
一个基础的类包含属性 (Properties/Fields) 和 方法 (Methods)。
dart
class Person {
// 属性 (实例变量)
String name;
int age;
// 构造函数:用于创建类的实例 (对象)
// this.name 是一个语法糖,等同于 this.name = name;
Person(this.name, this.age);
// 方法
void introduce() {
print('Hi, my name is $name and I am $age years old.');
}
}
void main() {
// 创建 Person 类的实例 (或称为 "对象")
var person1 = Person('David', 30);
var person2 = Person('Sarah', 25);
// 调用对象的方法
person1.introduce(); // 输出: Hi, my name is David and I am 30 years old.
person2.introduce(); // 输出: Hi, my name is Sarah and I am 25 years old.
}
继承 (Inheritance)
继承允许一个类 (子类) 获取另一个类 (父类) 的属性和方法。这在 Flutter 中至关重要,我们自定义的 Widget 通常都需要继承 StatelessWidget
或 StatefulWidget
。
dart
// 定义一个父类
class Animal {
void eat() {
print('The animal is eating.');
}
}
// Dog 类继承自 Animal 类
class Dog extends Animal {
void bark() {
print('Woof woof!');
}
}
void main() {
var myDog = Dog();
myDog.eat(); // 调用从父类继承来的方法
myDog.bark(); // 调用自己的方法
}
3. 异步编程 (Future
, async
, await
)
在 App 开发中,很多操作都是耗时的,比如从网络获取数据、读写手机文件。如果这些操作在主线程上执行,会造成界面卡顿,用户体验极差。Dart 使用 Future
对象和 async
/await
关键字来优雅地处理这些异步操作。
Future
: 一个Future
对象代表一个未来某个时刻会产生的结果。它有点像一张"承诺书",承诺在未来会给你一个值 (或一个错误)。async
: 这个关键字用在函数声明上,表示这个函数是一个异步函数,它的返回值会被自动包装成一个Future
。await
: 这个关键字必须用在async
函数内部,它会"等待"一个Future
完成,并返回其结果。在等待期间,它不会阻塞主线程,UI 依然可以响应用户操作。
示例:模拟网络请求
让我们模拟一个需要 2 秒才能返回数据的网络请求。
dart
import 'dart:async'; // 需要引入 'dart:async' 库来使用 Future
// 这是一个异步函数,它返回一个将在未来完成的 String
Future<String> fetchUserData() {
// Future.delayed 模拟了一个耗时操作
return Future.delayed(const Duration(seconds: 2), () => 'John Doe');
}
// 异步函数必须用 async 标记
void main() async {
print('Fetching user data...');
// 使用 await 等待 fetchUserData() 这个 Future 完成
// 在这两秒内,程序不会卡死
String userData = await fetchUserData();
// 等待结束后,才会执行下面的代码
print('Data fetched: $userData');
print('Program finished.');
}
运行结果:
erlang
Fetching user data...
(等待 2 秒)
Data fetched: John Doe
Program finished.
如果没有
await
,print(fetchUserData())
只会打印出Instance of 'Future<String>'
,而不是我们想要的结果 "John Doe"。await
就像是帮你把Future
这个"包裹"拆开,取出里面的东西。
完整可运行代码示例
您可以像之前一样,将以下完整代码复制到 DartPad 或您的 main.dart
文件中运行,来亲自体验这些概念。
dart
import 'dart:async';
// 1. 函数 (Function)
// 使用命名参数的函数
void printUserInfo({required String name, int age = 20}) {
print('User: $name, Age: $age');
}
// 2. 类 (Class)
class Greeter {
final String name; // final 属性,只能在构造时赋值
// 构造函数
Greeter(this.name);
// 方法
void sayHello() {
print('Hello from $name!');
}
}
// 3. 异步编程 (Async)
// 模拟一个耗时 2 秒的下载任务
Future<String> downloadFile() {
return Future.delayed(const Duration(seconds: 2), () {
return "Download complete!";
});
}
// 主函数 main 必须是 async 才能使用 await
void main() async {
print('--- 函数演示 ---');
printUserInfo(name: 'Alice');
printUserInfo(name: 'Bob', age: 35);
print('\n--- 类和对象演示 ---');
var greeter = Greeter('Dart');
greeter.sayHello();
print('\n--- 异步编程演示 ---');
print('Starting file download...');
// await 会暂停 main 函数的执行,但不会阻塞整个程序
// 它会等待 downloadFile() 这个 Future 完成
String result = await downloadFile();
// Future 完成后,await 返回结果,代码继续执行
print(result);
print('Main function finished.');
}
总结与展望
恭喜!您已经完成了 Dart 语言核心部分的快速入门。我们学习了:
- 函数的定义、箭头语法和灵活的参数(尤其是命名参数)。
- 类的定义、构造函数、属性、方法和继承。
- 异步编程 的核心
Future
、async
和await
,这是开发流畅应用的关键。
现在,您已经具备了阅读和编写大部分 Flutter 代码所需的 Dart 语言基础。从下一篇教程开始,我们将正式回归 Flutter,利用今天学到的知识,深入探索 Flutter 的核心概念:Widget。