类型系统
Dart 核心
数值类型 (int, double, num)
Dart 的数值类型包括 int(整数)和 double(浮点数),num 是两者的基类:
numbers.dart
void main() {
// int - 整数(平台相关,64位)
int age = 25;
int hex = 0xFF; // 十六进制
int binary = 0b1010; // 二进制
int octal = 0755; // 八进制
// double - 64位双精度浮点数
double pi = 3.14159;
double scientific = 1.5e-10; // 科学计数法
// num - int 或 double
num value = 10;
value = 3.14; // 可以是任意数值
// ========== 数值运算 ==========
int a = 10, b = 3;
print(a + b); // 13 加
print(a - b); // 7 减
print(a * b); // 30 乘
print(a / b); // 3.333... 除(返回double)
print(a ~/ b); // 3 整除
print(a % b); // 1 取余
print(a.abs()); // 10 绝对值
print((-5).abs()); // 5
// ========== 类型转换 ==========
int.parse('42'); // 字符串转int
double.parse('3.14'); // 字符串转double
42.toString(); // 转字符串
3.14159.toStringAsFixed(2); // '3.14'
3.14159.toInt(); // 3
// ========== 常用方法 ==========
print(42.isEven); // true 是否偶数
print(42.isOdd); // false 是否奇数
print(42.bitLength); // 6 位长度
print(42.toRadixString(2)); // '101010' 进制转换
print(3.14.round()); // 3 四舍五入
print(3.14.ceil()); // 4 向上取整
print(3.14.floor()); // 3 向下取整
print(3.14.truncate()); // 3 截断
}
字符串 (String)
Dart 字符串是 UTF-16 编码的字符序列,提供了丰富的操作方法:
strings.dart
void main() {
// ========== 字符串创建 ==========
String s1 = '单引号';
String s2 = "双引号";
String s3 = '''多行
字符串''';
String s4 = """
这是多行
字符串""";
// 原始字符串(不转义)
String raw = r'第一行\n第二行';
print(raw); // 输出: 第一行\n第二行
// ========== 字符串拼接 ==========
String name = 'Dart';
String greeting = 'Hello, ' + name + '!';
String template = 'Hello, $name!'; // 插值
String expr = '${name.length} chars'; // 表达式
// ========== 常用方法 ==========
String text = 'Hello, World!';
print(text.length); // 13 长度
print(text.isEmpty); // false 是否空
print(text.toUpperCase()); // 'HELLO, WORLD!'
print(text.toLowerCase()); // 'hello, world!'
print(text.trim()); // 去除首尾空白
print(text.contains('World')); // true 是否包含
print(text.startsWith('Hello')); // true 是否以...开头
print(text.endsWith('!')); // true 是否以...结尾
print(text.indexOf('o')); // 4 首次出现位置
print(text.lastIndexOf('o')); // 8 最后一次位置
// ========== 子字符串 ==========
print(text.substring(0, 5)); // 'Hello' 截取
print(text.split(', ')); // ['Hello', 'World!'] 分割
print(text.replaceAll('World', 'Dart')); // 替换所有
// ========== 格式化 ==========
String name = 'Alice';
int age = 30;
// padLeft/padRight
print(name.padLeft(10)); // ' Alice'
print(name.padRight(10, '*')); // 'Alice*****'
// ========== Rune(Unicode) ==========
String emoji = '😀';
print(emoji.runes.toList()); // [128512]
// 处理特殊字符
'你好'.runes.forEach((r) => print(String.fromCharCode(r)));
}
布尔类型 (bool)
Dart 布尔类型只有两个值:true 和 false。在条件判断中需要显式使用布尔值:
booleans.dart
void main() {
// ========== 布尔值 ==========
bool isActive = true;
bool isComplete = false;
// ========== 逻辑运算 ==========
bool a = true, b = false;
print(!a); // false 取反
print(a && b); // false 逻辑与
print(a || b); // true 逻辑或
// ========== 比较运算 ==========
int x = 10, y = 20;
print(x == y); // false 等于
print(x != y); // true 不等于
print(x > y); // false 大于
print(x < y); // true 小于
print(x >= y); // false 大于等于
print(x <= y); // true 小于等于
// ========== 空值判断 ==========
String? name;
print(name == null); // true
// ========== 链式判断 ==========
// ??= 空赋值
String? username;
username ??= 'Guest';
print(username); // 'Guest'
// ?. 条件成员访问
String? text;
print(text?.length); // null(不报错)
// ?? 空合并
String? input;
print(input ?? '默认值'); // '默认值'
// ========== 三元运算符 ==========
bool isOnline = true;
String status = isOnline ? '在线' : '离线';
// ========== ??= 简写 ==========
int? count;
count ??= 0; // 如果为null则赋值
}
列表 (List)
List 是 Dart 中最常用的集合类型,表示有序的元素集合:
lists.dart
void main() {
// ========== 创建 List ==========
var fruits = ['apple', 'banana', 'orange']; // 类型推断
List numbers = [1, 2, 3, 4, 5]; // 显式类型
// 固定长度列表
var fixed = List.filled(3, 0); // [0, 0, 0]
// 可变长度列表
var growable = List.empty(growable: true);
var fromIterable = List.from([1, 2, 3]);
// 生成列表
var generated = List.generate(5, (i) => i * i); // [0, 1, 4, 9, 16]
var repeated = List.filled(3, 'hi'); // ['hi', 'hi', 'hi']
// ========== 访问元素 ==========
print(fruits[0]); // 'apple' 下标访问
print(fruits.first); // 'apple' 第一个
print(fruits.last); // 'orange' 最后一个
print(fruits.length); // 3 长度
print(fruits.isEmpty); // false 是否为空
// ========== 修改列表 ==========
fruits.add('grape'); // 末尾添加
fruits.insert(1, 'mango'); // 插入
fruits.remove('banana'); // 移除
fruits.removeAt(0); // 移除下标
fruits.clear(); // 清空
// ========== 遍历 ==========
for (var fruit in fruits) {
print(fruit);
}
fruits.forEach((f) => print(f));
// ========== 转换 ==========
var doubled = numbers.map((n) => n * 2).toList(); // [2, 4, 6, 8, 10]
var evens = numbers.where((n) => n % 2 == 0).toList(); // [2, 4]
var sum = numbers.fold(0, (a, b) => a + b); // 15
// ========== 排序 ==========
numbers.sort((a, b) => b - a); // 降序
numbers.shuffle(); // 随机打乱
// ========== 切片 ==========
print(numbers.sublist(1, 3)); // [2, 3] 截取
// ========== 展开运算符 ==========
var flat = [1, ...[2, 3], 4]; // [1, 2, 3, 4]
List? extra;
var safe = [1, ...?extra, 2]; // [1, 2](extra为null时不报错)
}
集合 (Set)
Set 是无序且不重复的元素集合,适合用于去重和成员检测:
sets.dart
void main() {
// ========== 创建 Set ==========
var colors = {'red', 'green', 'blue'}; // 类型推断
Set numbers = {1, 2, 3}; // 显式类型
// 空集合
var empty = {};
var emptySet = Set.empty();
// ========== 基本操作 ==========
print(colors.length); // 3 长度
print(colors.isEmpty); // false 是否为空
print(colors.contains('red')); // true 是否包含
print(colors.containsAll({'red', 'blue'})); // 是否包含所有
// ========== 添加/移除 ==========
colors.add('yellow');
colors.addAll({'purple', 'orange'});
colors.remove('green');
colors.clear();
// ========== 集合运算 ==========
var a = {1, 2, 3, 4};
var b = {3, 4, 5, 6};
print(a.union(b)); // {1, 2, 3, 4, 5, 6} 并集
print(a.intersection(b)); // {3, 4} 交集
print(a.difference(b)); // {1, 2} 差集
print(a.lookup(2)); // 2 查找(不存在返回null)
// ========== 去重 ==========
var withDup = [1, 2, 2, 3, 3, 3];
var unique = withDup.toSet(); // {1, 2, 3}
// ========== 遍历 ==========
colors.forEach((c) => print(c));
for (var c in colors) {
print(c);
}
// ========== 类型转换 ==========
var list = [1, 2, 3];
var set = list.toSet(); // List -> Set
var backToList = set.toList(); // Set -> List
}
映射 (Map)
Map 是键值对集合,每个键唯一,值可以重复:
maps.dart
void main() {
// ========== 创建 Map ==========
var scores = {'Alice': 90, 'Bob': 85, 'Carol': 92}; // 类型推断
Map ages = {'Tom': 25, 'Jerry': 30};
// 空 Map
var empty = {};
var emptyMap = Map.empty();
// 构造方法
var from = Map.from({'a': 1, 'b': 2});
var of = Map.of({1: 'one', 2: 'two'});
var fromIterables = Map.fromIterables([1, 2], ['one', 'two']);
var fromEntries = Map.fromEntries([
MapEntry('x', 10),
MapEntry('y', 20),
]);
// ========== 访问 ==========
print(scores['Alice']); // 90 获取值
print(scores['Unknown']); // null 不存在返回null
// 常用方法
print(scores.length); // 3 键值对数量
print(scores.isEmpty); // false 是否为空
print(scores.containsKey('Bob')); // true 是否包含键
print(scores.containsValue(90)); // true 是否包含值
print(scores.keys); // (Alice, Bob, Carol) 键集合
print(scores.values); // (90, 85, 92) 值集合
// ========== 修改 ==========
scores['Bob'] = 88; // 修改值
scores['David'] = 95; // 添加新键值对
scores.addAll({'Eve': 88, 'Frank': 91}); // 批量添加
scores.remove('Bob'); // 移除
scores.clear(); // 清空
// ========== 获取默认值 ==========
// putIfAbsent: 如果键不存在则设置值
scores.putIfAbsent('Alice', () => 100);
// ========== 遍历 ==========
scores.forEach((key, value) {
print('$key: $value');
});
for (var entry in scores.entries) {
print('${entry.key} = ${entry.value}');
}
// ========== 映射操作 ==========
var mapped = scores.map((k, v) => MapEntry(k.toUpperCase(), v + 10));
var keys = scores.keys.map((k) => k.toUpperCase()).toList();
// ========== 合并 ==========
var m1 = {'a': 1, 'b': 2};
var m2 = {'b': 3, 'c': 4};
var merged = {...m1, ...m2}; // {'a': 1, 'b': 3, 'c': 4}
}
Rune、Symbol、Function
Rune 是 UTF-32 字符编码,Symbol 表示标识符,Function 是函数类型:
rune_symbol.dart
void main() {
// ========== Rune ==========
// String 是 UTF-16 序列,有些字符需要多个代码单元
// Rune 是 UTF-32 完整字符
String emoji = '😀';
print(emoji.runes); // (128512) Unicode 码点
// 遍历 Rune
'你好'.runes.forEach((r) {
print('Code: $r, Char: ${String.fromCharCode(r)}');
});
// 处理特殊字符
String name = 'Café';
print(name.runes.toList()); // [67, 97, 102, 233]
// 使用 Rune 构造字符串
String fromRunes = String.fromCharCodes([72, 101, 108, 108, 111]); // 'Hello'
// ========== Symbol ==========
// Symbol 表示标识符,用于反射和元编程
// 定义 Symbol
Symbol sym = #myIdentifier;
Symbol methodSym = #toString;
Symbol classSym = #MyClass;
// 字符串转 Symbol
Symbol fromString = Symbol('myIdentifier');
// 比较
print(sym == fromString); // true
// ========== Function 类型 ==========
// 函数是一等公民,可以赋值给变量
Function add = (int a, int b) => a + b;
print(add(2, 3)); // 5
// 具体函数类型
int Function(int, int) multiply = (a, b) => a * b;
print(multiply(4, 5)); // 20
// ========== Type 类型 ==========
// 表示运行时类型信息
Type intType = int;
Type stringType = String;
print(intType); // 'int'
print(42.runtimeType); // int
}
枚举 (enum)
枚举是一种特殊的类,用于定义固定数量的常量值:
enums.dart
void main() {
// ========== 基础枚举 ==========
enum Color { red, green, blue }
print(Color.red); // Color.red
print(Color.red.index); // 0
// 遍历枚举
for (var c in Color.values) {
print(c);
}
// switch 匹配
var color = Color.blue;
switch (color) {
case Color.red:
print('红色');
break;
case Color.green:
print('绿色');
break;
case Color.blue:
print('蓝色');
}
// ========== 带值的枚举 ==========
enum Status {
success(200, '成功'),
error(500, '错误'),
pending(100, '处理中');
final int code;
final String message;
const Status(this.code, this.message);
String toJson() => '{"code": $code, "message": "$message"}';
}
print(Status.success.code); // 200
print(Status.success.message); // '成功'
}
enum Priority {
low(1),
medium(2),
high(3);
final int value;
const Priority(this.value);
bool get isHigh => this == Priority.high;
}
void process(Priority priority) {
if (priority.isHigh) {
print('高优先级任务');
}
}
泛型
泛型提供类型参数化,使代码更加灵活和安全:
generics.dart
// ========== 泛型类 ==========
class Box {
T? _value;
void set(T value) => _value = value;
T get() => _value as T;
}
class Pair {
final K key;
final V value;
Pair(this.key, this.value);
}
// ========== 泛型约束 ==========
class Repository {
final Map _cache = {};
T? findById(int id) => _cache[id];
void save(T entity) => _cache[entity.id] = entity;
}
abstract class Entity {
int get id;
}
// ========== 泛型方法 ==========
T first(List items) => items.first;
T? firstOrNull(List items) =>
items.isEmpty ? null : items.first;
R map(List items, R Function(T) transform) =>
items.map(transform).toList();
void main() {
var stringBox = Box();
stringBox.set('Dart');
print(stringBox.get());
var pair = Pair('name', 'Dart');
print('${pair.key}: ${pair.value}');
var users = [User(1), User(2)];
var repo = Repository();
}
class User implements Entity {
final int id;
User(this.id);
@override
int get id => id;
}
类型推断
Dart 具有强大的类型推断能力:
type_inference.dart
void main() {
// var - 类型推断
var message = 'Hello'; // 推断为 String
var count = 42; // 推断为 int
var prices = [1.5, 2.0]; // 推断为 List
// dynamic - 动态类型(绕过类型检查)
dynamic anything = 'str';
anything = 123; // 可以是任何类型
// Object - 任何类型
Object obj = 'anything';
obj = 42;
// 泛型推断
var stringMap = {'key': 'value'};
var intList = [1, 2, 3];
// 类型转换
var num = 42;
var str = num.toString();
var doubleNum = double.parse('3.14');
// 明确类型声明(推荐)
String name = 'Dart';
List numbers = [1, 2, 3];
Map data = {'name': 'test', 'value': 42};
// final 和 const 也支持类型推断
final inferredList = [1, 2, 3]; // List
const inferredMap = {'a': 1}; // Map
}