4、Dart语言速通(上):变量与常量、内置类型、函数、操作符
好,咱们开始进入Dart语言的核心部分。说实话,很多初学者一上来就啃语法书,结果越看越晕。我的建议是——先动手,再理解。你写几行代码,跑起来,再回头看概念,会清晰很多。
这一章,咱们把Dart最常用的几个基础模块过一遍:变量、常量、内置类型、函数和操作符。这些都是你写Flutter时每天都要打交道的东西。
4.1 变量与常量:先搞清楚“能不能变”
Dart是强类型语言,但它的类型声明方式很灵活。我个人习惯是:能确定类型的,就显式声明;不确定的,用var让编译器去推。
var name = '张三'; // 自动推断为String
int age = 25; // 显式声明
double height = 1.75; // 浮点数
bool isStudent = true; // 布尔值
这里有个坑——var一旦赋值,类型就锁死了。你不能把一个var name = '张三'后面再赋值为数字。我曾经在项目里见过有人这么写,结果编译直接报错。
var不是动态类型,它只是让编译器帮你推断类型。一旦推断完成,类型就固定了。
再说常量。Dart里有两个关键字:final和const。很多人搞混,其实很简单:
final:运行时赋值,赋值后不可改。适合从接口获取的数据。const:编译时就确定值。适合固定配置。
final currentTime = DateTime.now(); // 运行时确定
const pi = 3.14159; // 编译时确定
嗯,这里要注意:const要求值在编译期就能算出来。你不能写const time = DateTime.now(),因为DateTime.now()是运行时才执行的。
4.2 内置类型:Dart给你准备好了哪些“积木”
Dart的内置类型不多,但够用。咱们挑几个重点说。
4.2.1 数字:int和double
Dart里没有float,只有int和double。它们都继承自num。你想想看,这设计其实挺合理的——整数和小数,够用了。
int a = 10;
double b = 3.14;
num c = 42; // 可以是int或double
.round()、.toInt()、.toStringAsFixed(2)等方法做类型转换,很常用。
4.2.2 字符串:单引号还是双引号?
我个人习惯用单引号。除非字符串里本身有单引号,我才用双引号。Dart支持字符串插值,用$变量名或${表达式}。
var name = '李四';
print('你好,$name'); // 你好,李四
print('2 + 3 = ${2 + 3}'); // 2 + 3 = 5
多行字符串用三个引号:
var multiLine = '''
这是第一行
这是第二行
''';
4.2.3 布尔值:只有true和false
Dart的布尔值很严格。你不能像JavaScript那样写if (name)来判断非空。必须显式写if (name.isNotEmpty)。我第一次从JS转Dart时就被这个坑过。
true是true,其他都不是。0、空字符串、null都不会被隐式转换为false。
4.2.4 列表和映射:最常用的集合
列表就是数组,映射就是字典。写法很直观:
var list = [1, 2, 3]; // List<int>
var map = {'name': '王五', 'age': 30}; // Map<String, dynamic>
列表支持展开操作符...,这个在Flutter里拼Widget时特别好用:
var list1 = [1, 2];
var list2 = [0, ...list1, 3]; // [0, 1, 2, 3]
4.3 函数:Dart里函数是一等公民
这句话什么意思?说白了,函数可以像变量一样赋值、传参、返回。这在Flutter里太常见了——你写回调、事件处理,全是函数。
4.3.1 基本写法
int add(int a, int b) {
return a + b;
}
如果函数体只有一行表达式,可以用箭头语法:
int add(int a, int b) => a + b;
我个人更喜欢箭头语法,简洁。但注意,箭头后面只能跟表达式,不能跟语句。
4.3.2 可选参数:位置参数和命名参数
Dart支持两种可选参数。我建议你用命名参数,可读性更好:
// 命名参数(推荐)
void greet({required String name, int age = 18}) {
print('你好,$name,你$age岁了');
}
// 调用
greet(name: '赵六', age: 25);
required关键字表示这个参数必须传。不加required的就是可选参数,可以给默认值。
Text('你好')其实传的是data参数,但它是位置参数的特例。
4.3.3 匿名函数:回调的基石
匿名函数没有名字,直接定义直接用。最常见的场景就是列表遍历:
var list = [1, 2, 3];
list.forEach((item) {
print(item);
});
箭头写法更简洁:
list.forEach((item) => print(item));
4.4 操作符:别被“?? ”吓到
Dart的操作符大部分和其他语言一样。但有几个是Dart特有的,我重点说一下。
4.4.1 类型判定操作符
| 操作符 | 作用 | 示例 |
|---|---|---|
as |
类型转换 | obj as String |
is |
类型判断 | obj is String |
is! |
类型否定判断 | obj is! String |
我建议你多用is,少用as。因为as如果类型不匹配会抛异常。用is先判断,更安全。
4.4.2 空安全操作符:?? 和 ??=
这是Dart 2.12引入的特性。说白了就是处理null的语法糖:
var name = null;
var displayName = name ?? '默认名称'; // 如果name为null,用默认值
name ??= '新名称'; // 如果name为null,才赋值
我曾经在项目里看到有人写一堆if (xxx != null)的嵌套判断,后来全改成??了,代码清爽很多。
4.4.3 级联操作符:..
这个操作符让你可以对同一个对象连续操作。在Flutter里配置Widget时特别好用:
var sb = StringBuffer()
..write('Hello')
..write(' ')
..write('World');
你想想看,如果没有..,你得写三行sb.write(...)。现在一行搞定。
4.5 小结:先跑起来再说
这一章的内容,说白了就是Dart的“ABC”。你不用全部记住,但要知道它们存在。我建议你打开DartPad,把上面的代码都敲一遍。遇到报错别慌,看看错误信息,改一改,跑通了,你就记住了。
下一章咱们继续聊Dart的面向对象特性——类、继承、接口这些。到时候你会发现,Flutter里到处都是类和对象。
- 变量用
var或显式类型声明,常量用final或const - 内置类型:int、double、String、bool、List、Map
- 函数是一等公民,支持箭头语法和命名参数
- 空安全操作符
??和级联操作符..是Dart特色