Dart 语法入门:从 C 迁移到新语言
把后面会遇到的写法在这一篇集中解释。先读普通数值和函数,再认识集合、空值、对象与回调,每段都能独立观察结果。
1 · 变量、类型与不可重新赋值
放入 main(),运行观察
var count = 1;
count = 2;
final readings = <int>[3900, 4000];
readings.add(4100);
const title = 'Watch';
double voltage = 4.0;
bool connected = false;
print('$title: $voltage V, $connected');var 让编译器从初值推断类型,count 仍然是整数,不能随后赋成字符串。final 表示这个变量只能赋值一次;它指向的列表仍可增加元素。const 声明编译时常量,常量列表的内容也不能修改。int、double、bool、String 分别表示整数、浮点数、布尔值和字符串。
字符串中的 $name 或 ${表达式} 插入计算结果。与 C 的字符数组不同,Dart 不要求手工安排字符串缓冲或结尾的零字符。对象的内存回收由运行环境管理,但监听、定时器等活动资源仍要按生命周期停止。
2 · 列表、映射和尖括号
列表按下标查找,Map 按键查找
final values = <int>[10, 20, 30];
final names = <int, String>{0: 'Lying', 3: 'Walking'};
for (final value in values) {
print(value);
}
print(values[1]);
print(names[3]);List
Dart 的 / 产生除法结果,~/ 用于整数除法。if、for、while、return 的基本逻辑沿用熟悉的写法;条件必须是 bool,不能直接把整数当作真假。
3 · 函数、命名参数与回调
完整片段 · 输出 6 和 clicked
int add(int a, int b, {int offset = 0}) {
return a + b + offset;
}
void main() {
print(add(2, 3, offset: 1));
void Function() action = () => print("clicked");
action();
}花括号内是命名参数,调用时写 offset: 1;有默认值时可以省略。required 表示这个命名参数必须提供。位置参数按顺序传递,可选位置参数使用方括号。函数只有一个返回表达式时,可以写成 => 表达式。
void Function() 表示“不接收参数、不返回结果”的函数类型。() => print(...) 是匿名函数,先交给 action,action() 才执行。Flutter 按钮也用这种方式接收回调;onPressed: action 交付函数,onPressed: action() 会在构建页面时就调用它。
4 · 空值安全:几个符号究竟在检查什么
放入 main(),先看 null,再看赋值之后
String? deviceName;
print(deviceName?.length);
print(deviceName ?? 'No device');
deviceName = 'SmartWatch';
print(deviceName.length);String? 允许值为 null,即没有对象;普通 String 不能直接保存 null。?. 只在对象存在时访问成员,?? 在左边为 null 时采用右边默认值。! 是程序员声明“这里一定不为 null”,若判断错误会在运行时失败。处理扫描失败时通常应明确判断,而不是到处加 !。
late 表示变量稍后会在使用前初始化,不会自动创建对象。未初始化就使用仍然会失败。页面销毁后是否仍然有效,是另一个生命周期问题,不能用空值检查替代。
5 · 类、构造函数、继承与重写
类定义放在 main() 外;main() 中创建 BatteryMeasurement(4000)
class Measurement {
final int millivolts;
Measurement(this.millivolts);
String describe() => "$millivolts mV";
}
class BatteryMeasurement extends Measurement {
BatteryMeasurement(super.millivolts);
@override
String describe() => "Battery: ${super.describe()}";
}类把一类对象的数据和操作写在一起,millivolts 是字段,describe 是方法。构造函数与类同名,this.millivolts 把传入值放进当前对象。extends 继承已有类型的能力,super 访问父类;@override 明确声明这里重写已有方法,便于工具检查名称和签名。
Flutter 页面会继承框架的 Widget 类型并重写 build;它是后面解释界面的必要语法,不要求先建立一套设备对象框架。import 导入其他文件或库;名称前的下划线表示库内私有,而不是 C 的文件级 static。
运行下载示例,解释为什么 final 列表还能增加元素。将 onPressed 的两种写法分别口头说明执行时刻,删除一个必要的空值处理,观察分析器给出的错误。
资料与代码
配套文件
先复制到独立练习目录;用法见 支线示例说明。完整 Flutter 小应用见 tutorial/examples/flutter_watch/README.md。