前端学习-Dart官方文档学习-002-类型
基本类型
Dart支持以下类型:
Numbers (int, double)
Strings (String)
Booleans (bool)
Records ((value1, value2))
Lists (List, also known as arrays)
Sets (Set)
Maps (Map)
Runes (Runes; often replaced by the characters API)
Symbols (Symbol)
The value null (Null)
Object: The superclass of all Dart classes except Null.
Enum: The superclass of all enums.
Future and Stream: Used in asynchrony support.
Iterable: Used in for-in loops and in synchronous generator functions.
Never: Indicates that an expression can never successfully finish evaluating. Most often used for functions that always throw an exception.
dynamic: Indicates that you want to disable static checking. Usually you should use Object or Object? instead.
void: Indicates that a value is never used. Often used as a return type.
Numbers(int double)
- If num and its subtypes don't have what you're looking for, the dart:math library might.
// int 类型
var x = 1;
var hex = 0xDEADBEEF;
// double 类型
var y = 1.1;
var exponents = 1.42e5;
// num类型(可以是int也可以是double)
num x = 1; // x can have both int and double values
x += 2.5;
// int 可转为 double
double z = 1; // Equivalent to double z = 1.0.
- 将 String 转为 num , num 转为 String
// String -> int
var one = int.parse('1');
assert(one == 1);
// String -> double
var onePointOne = double.parse('1.1');
assert(onePointOne == 1.1);
// int -> String
String oneAsString = 1.toString();
assert(oneAsString == '1');
// double -> String
String piAsString = 3.14159.toStringAsFixed(2);
assert(piAsString == '3.14');
Strings
// 使用''或""创建String
var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";
// 两种连接字符串的方式:相邻字面量 或 使用+
var s1 = 'String '
'concatenation'
" works even over line breaks.";
assert(s1 ==
'String concatenation works even over '
'line breaks.');
var s2 = 'The + operator ' + 'works, as well.';
assert(s2 == 'The + operator works, as well.');
// ${expression}嵌入表达式 或 $variable 嵌入变量
var s = 'string interpolation';
assert('Dart has $s, which is very handy.' ==
'Dart has string interpolation, '
'which is very handy.');
assert('That deserves all caps. '
'${s.toUpperCase()} is very handy!' ==
'That deserves all caps. '
'STRING INTERPOLATION is very handy!');
// 对于多行String 使用'''
var s1 = '''
You can create
multi-line strings like this one.
''';
var s2 = """This is also a
multi-line string.""";
// r开头创建raw字符串 转义字符等特殊字符会被直接输出,而不会被自动转义;如\n会直接输出,而不会换行
var s = r'In a raw string, not even \n gets special treatment.';
Booleans
由于Dart有类型安全,类似if (nonbooleanValue) or assert (nonbooleanValue)这样的代码不能使用,需按以下方式使用
// Check for an empty string.
var fullName = '';
assert(fullName.isEmpty);
// Check for zero.
var hitPoints = 0;
assert(hitPoints == 0);
// Check for null.
var unicorn = null;
assert(unicorn == null);
// Check for NaN.
var iMeantToDoThis = 0 / 0;
assert(iMeantToDoThis.isNaN);
Runes and grapheme clusters
import 'package:characters/characters.dart';
void main() {
var hi = 'Hi 🇩🇰';
print(hi);
print('The end of the string: ${hi.substring(hi.length - 1)}');
print('The last character: ${hi.characters.last}');
}
// 输出为
dart run bin/main.dart
Hi 🇩🇰
The end of the string: ???
The last character: 🇩🇰
Symbols
they're invaluable for APIs that refer to identifiers by name
#radix
#bar
Records 记录
语法
var record = ('first', a: 2, b: true, 'last');
(int, int) swap((int, int) record) {
var (a, b) = record;
return (b, a);
}
使用示例
// 定义 Record
var record = ('first', a: 2, b: true, 'last');
// 访问 Record 中的匿名字段
print(record.$1);
print(record.$2);
// 访问 Record 中的命名字段
print(record.a);
print(record.b);
集合Collections
Lists
var list = [1, 2, 3]; // Dart infers that list has type List<int>. If you try to add non-integer objects to this list, the analyzer or runtime raises an error.
var list = [
'Car',
'Boat',
'Plane',
];
assert(list.length == 3);
assert(list[1] == 2);
var constantList = const [1, 2, 3];
// constantList[1] = 1; // This line will cause an error.
Sets
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};
var names = <String>{};
// Set<String> names = {}; // This works, too.
// var names = {}; // Creates a map, not a set.
final constantSet = const {
'fluorine',
'chlorine',
'bromine',
'iodine',
'astatine',
};
// constantSet.add('helium'); // This line will cause an error.
添加元素、查看数量
var elements = <String>{};
elements.add('fluorine');
elements.addAll(halogens);
assert(elements.length == 5);
Maps
var gifts = {
// Key: Value
'first': 'partridge',
'second': 'turtledoves',
'fifth': 'golden rings'
};
var nobleGases = {
2: 'helium',
10: 'neon',
18: 'argon',
};
var gifts = Map<String, String>();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';
var nobleGases = Map<int, String>();
nobleGases[2] = 'helium';
nobleGases[10] = 'neon';
nobleGases[18] = 'argon';
// 使用[]=添加键值对
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds'; // Add a key-value pair
// 检索值
var gifts = {'first': 'partridge'};
assert(gifts['first'] == 'partridge');
// If you look for a key that isn't in a map, you get null in return:
var gifts = {'first': 'partridge'};
assert(gifts['fifth'] == null);
// Use .length to get the number of key-value pairs in the map:
var gifts = {'first': 'partridge'};
gifts['fourth'] = 'calling birds';
assert(gifts.length == 2);
// To create a map that's a compile-time constant, add const before the map literal:
final constantMap = const {
2: 'helium',
10: 'neon',
18: 'argon',
};
// constantMap[2] = 'Helium'; // This line will cause an error.
Operators
Spread operators 扩展操作符 (... 和 ...?)
spread operator (...)
var list = [1, 2, 3];
var list2 = [0, ...list];
assert(list2.length == 4);
null-aware spread operator (...?)
var list2 = [0, ...?list];
assert(list2.length == 1);
Control-flow operators (conditionals (if) and repetition (for))
var nav = ['Home', 'Furniture', 'Plants', if (promoActive) 'Outlet'];
var nav = ['Home', 'Furniture', 'Plants', if (login case 'Manager') 'Inventory'];
var listOfInts = [1, 2, 3];
var listOfStrings = ['#0', for (var i in listOfInts) '#$i'];
assert(listOfStrings[1] == '#1');
Generics 泛型
例如 List
使用泛型的好处:让代码更好,减少代码重复
var names = <String>[];
names.addAll(['Seth', 'Kathy', 'Lars']);
names.add(42); // Error
abstract class ObjectCache {
Object getByKey(String key);
void setByKey(String key, Object value);
}
abstract class StringCache {
String getByKey(String key);
void setByKey(String key, String value);
}
// 以上两个可简写为下面一个,T作为占位符
abstract class Cache<T> {
T getByKey(String key);
void setByKey(String key, T value);
}
add (for lists and sets) or <keyType, valueType> (for maps) before the opening bracket. Here is an example of using typed literals:
var names = <String>['Seth', 'Kathy', 'Lars'];
var uniqueNames = <String>{'Seth', 'Kathy', 'Lars'};
var pages = <String, String>{
'index.html': 'Homepage',
'robots.txt': 'Hints for web robots',
'humans.txt': 'We are people, not machines'
};
Using parameterized types with constructors
var nameSet = Set<String>.from(names);
var views = Map<int, View>();
Dart generic types carry their type information around at runtime. For example, you can test the type of a collection:
var names = <String>[];
names.addAll(['Seth', 'Kathy', 'Lars']);
print(names is List<String>); // true
In contrast, generics in Java use erasure, which means that generic type parameters are removed at runtime. In Java, you can test whether an object is a List, but you can't test whether it's a List
Restricting the parameterized type 限制参数化类型
class Foo<T extends SomeBaseClass> {
// Implementation goes here...
String toString() => "Instance of 'Foo<$T>'";
}
class Extender extends SomeBaseClass {...}
// 使用
var someBaseClassFoo = Foo<SomeBaseClass>();
var extenderFoo = Foo<Extender>();
var foo = Foo(); // 不指定泛型参数也是可以的
print(foo); // Instance of 'Foo<SomeBaseClass>'
var foo = Foo<Object>(); // 指定任何非somebaseclass类型都会导致错误
泛型方法
T first<T>(List<T> ts) {
// Do some initial work or error checking, then...
T tmp = ts[0];
// Do some additional checking or processing...
return tmp;
}
Typedefs 别名
typedef IntList = List<int>;
IntList il = [1, 2, 3];
typedef ListMapper<X> = Map<X, List<X>>;
Map<String, List<String>> m1 = {}; // Verbose.
ListMapper<String> m2 = {}; // Same thing but shorter and clearer.
类型体系
不要将动态类型的 List 看做是有类型的 List
当期望在一个 List 中可以包含不同类型的对象时,动态列表是很好的选择。但是不能将动态类型的 List 看做是有类型的 List 。
void main() {
List<Cat> foo = <dynamic>[Dog()]; // Error
List<dynamic> bar = <dynamic>[Dog(), Cat()]; // OK
}
类型推断
分析器 (analyzer) 可以推断字段,方法,局部变量和大多数泛型类型参数的类型。当分析器没有足够的信息来推断出一个特定类型时,会使用 dynamic 作为类型
// 显式写明类型
Map<String, dynamic> arguments = {'argA': 'hello', 'argB': 42};
// Dart推断类型
var arguments = {'argA': 'hello', 'argB': 42}; // Map<String, Object>
参数类型推断
// Inferred as if you wrote <int>[].
List<int> listOfInt = [];
// Inferred as if you wrote <double>[3.0].
var listOfDouble = [3.0];
// Inferred as Iterable<int>.
var ints = listOfDouble.map((x) => x.toInt());
替换类型
普通类型赋值
消费者接受类型,生产者产生类型。
Cat c = Cat(); // Cat c 是 消费者 而 Cat() 是 生产者
Animal c = Cat(); // 允许的,因为 Animal 是 Cat 的父类。
MaineCoon c = Cat(); // MaineCoon c 替换 Cat c 会打破类型的安全性,因为父类可能会提供一种具有不同行为的 Cat ,例如 Lion
Cat c = MaineCoon(); // 在生产者的位置,可以安全地将生产类型 (Cat) 替换成一个更具体的类型 (MaineCoon) 的对象。因此,下面的操作是允许的:
泛型赋值
List<MaineCoon> myMaineCoons = ...
List<Cat> myCats = myMaineCoons; // 可以将 MaineCoon 类型的 List 赋值给 myCats ,因为 List<MaineCoon> 是 List<Cat> 的子类型
List<Animal> myAnimals = ...
List<Cat> myCats = myAnimals; // 这个赋值不能通过静态分析,因为它创建了一个隐式的向下转型 (downcast),这在非 dynamic 类型中是不允许的,比如 Animal。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 易语言 —— 开山篇