Dart 语言之旅
作者:互联网
重要概念
- 所有变量引用的都是对象,每个对象都是一个类的实例。数字、函数以及
null
都是对象。除去null
以外(如果你开启了空安全), 所有的类都继承于 Object 类。 - 尽管 Dart 是强类型语言,但是在声明变量时指定类型是可选的,因为 Dart 可以进行类型推断。
- 如果你开启了空安全,变量在未声明为可空类型时不能为
null
。你可以通过在类型后加上问号 (?
) 将类型声明为可空。例如,int?
类型的变量可以是整形数字或null
。如果你 明确知道 一个表达式不会为空,但 Dart 不这么认为时,你可以在表达式后添加!
来断言表达式不为空(为空时将抛出异常)。例如:int x = nullableButNotNullInt!
- 如果你想要显式地声明允许任意类型,使用
Object?
(如果你 开启了空安全)、 Object 或者 特殊类型 dynamic 将检查延迟到运行时进行。 - Dart 支持泛型,比如
List<int>
(表示一组由 int 对象组成的列表)或List<Object>
(表示一组由任何类型对象组成的列表)。 - Dart 支持顶级函数(例如
main
方法),同时还支持定义属于类或对象的函数(即 静态 和 实例方法)。你还可以在函数中定义函数(嵌套 或 局部函数)。 - Dart 支持顶级 变量,以及定义属于类或对象的变量(静态和实例变量)。实例变量有时称之为域或属性。
- Dart 没有类似于 Java 那样的
public
、protected
和private
成员访问限定符。如果一个标识符以下划线 (_
) 开头则表示该标识符在库内是私有的。可以查阅 库和可见性 获取更多相关信息。 - Dart 中 表达式 和 语句 是有区别的,表达式有值而语句没有。比如条件表达式
expression condition ? expr1 : expr2
中含有值expr1
或expr2
。与 if-else 分支语句相比,if-else
分支语句则没有值。一个语句通常包含一个或多个表达式,但是一个表达式不能只包含一个语句。 - Dart 工具可以显示 警告 和 错误 两种类型的问题。警告表明代码可能有问题但不会阻止其运行。错误分为编译时错误和运行时错误;编译时错误代码无法运行;运行时错误会在代码运行时导致 异常。
变量
var name = 'Geek JKFX';
变量仅存储对象的引用。如果一个对象的引用不局限于单一的类型,可以将其指定为 Object
(或 dynamic
)类型。
本文遵循 风格建议指南 中的建议,通过
var
声明局部变量而非使用指定的类型。
默认值
在 Dart 中,未初始化以及可空类型的变量拥有一个默认的初始值 null
。(如果你未迁移至 空安全,所有变量都为可空类型。)即便数字也是如此,因为在 Dart 中一切皆为对象,数字也不例外。
如果你启用了空安全,那么你初始化一个非可空的变量时必须赋予初值。
你不必在定义声明一个局部变量的时候去进行初始化,但你需要使用其之前赋值。
顶层和类变量都是懒式初始化,初始化代码将在首次使用变量的时候执行。
Late 变量
Dart 2.12 添加了 late
修饰符,其有如下两个使用场景:
- 声明一个非空变量,其在声明之后进行初始化操作
- 懒式初始化一个变量
如果你确保一个变量在使用之前被赋值,而Dart的控制流分析并没有检测到,你可以通过late
修饰一个变量修复错误提示。
late String description;
void main() {
description = 'Feijoada!';
print(description);
}
如果你并没有初始化
late
变量,当变量被使用的时候会抛出运行时错误。
当你使用late
修饰变量而在声明变量时不进行初始化,那么初始化操作将在变量首次被使用的时候执行。懒式初始化有几个方便的场景:
- 一个变量初始化操作非常耗时,并且不确定会被使用。
- 你初始化一个实例变量,并且初始化操作需要访问
this
。
Final 和 Const
如果你不想更改一个变量,可以使用关键字 final
或者 const
修饰变量,这两个关键字可以替代 var
关键字或者加在一个具体的类型前。一个 final
变量只可以被赋值一次;一个 const
变量是一个编译时常量(const
变量同时也是 final
的)。顶层的 final
变量或者类的 final
变量在其第一次使用的时候被初始化。
实例变量 可以是
final
的但不可以是const
。
使用关键字 const
修饰变量表示该变量为 编译时常量 。如果使用 const
修饰类中的变量,则必须加上 static
关键字,即 static const
(顺序不能颠倒)。在声明 const
变量时可以直接为其赋值,也可以使用其它的 const
变量为其赋值。
const
关键字不仅仅可以用来定义常量,还可以用来创建 常量值,该常量值可以赋予给任何变量。你也可以将构造函数声明为 const
的,这种类型的构造函数创建的对象是不可改变的。
你可以在常量中使用 类型检查和强制类型转换 (is
和 as
)、 集合中的 if 以及 展开操作符 (...
和 ...?
)。
尽管
final
对象不可以被修改,但是它的字段是可以改变的。对比之下,const
对象和它的字段都是不可以被改变的,他们都是immutable的。
内置类型
Dart 语言支持下列内容:
-
Numbers (
int
,double
) -
Strings (
String
) -
Booleans (
bool
) -
Lists (也被称为 arrays)
-
Sets (
Set
) -
Maps (
Map
) -
Runes (常用于在
Characters
API 中进行字符替换) -
Symbols (
Symbol
) -
The value null (
Null
)
一些特殊类型在Dart语言中也有着特别作用:
Object
所有Dart类的超类(superclass),除了Null
之外。Future
和Stream
用在 异步支持 中。Iterable
用于 for-in 循环 以及同步 生成器函数。Never
表明一个表达式永远不会成功地完成评估(evaluating)。多数情况下用于总是抛出一个异常的函数。dynamic
表明你想要禁用静态检查。通常你应该使用Object
或Object?
代替。void
表明一个永远不会被使用的值。通常用作返回类型。
Object
、Object?
、Null
和Never
类在类层次(class hierarchy)中有着特殊作用,描述在top-and-bottom和理解空安全中。
Number
Dart 支持两种 Number
类型:
int:整数值;长度不超过 64 位,具体取值范围 依赖于不同的平台。在 DartVM 上其取值位于 -2^63 至 2^63 - 1 之间。在 Web 上,整型数值代表着 JavaScript 的数字(64 位无小数浮点型),其允许的取值范围在 -2^53 至 2^53 - 1 之间。
double:64 位的双精度浮点数字,且符合 IEEE 754 标准。
int
和 double
都是 num 的子类。 num 中定义了一些基本的运算符比如 +、-、*、/ 等,还定义了 abs()
、ceil()
和 floor()
等方法(位运算符,比如 >> 定义在 int 中)。如果 num 及其子类不满足你的要求,可以查看 dart:math 库中的 API。
下面是字符串和数字之间转换的方式:
// 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');
整型支持传统的位移操作,比如移位(<<
、>>
和 >>>
)、补码 (~
)、按位与 (&
)、按位或 (|
) 以及按位异或 (^
)。
更多示例请查看 移位操作符 小节。
String
Dart 字符串(String 对象)包含了 UTF-16 编码的字符序列。可以使用单引号或者双引号来创建字符串。
在字符串中,请以 ${表达式}
的形式使用表达式,如果表达式是一个标识符,可以省略掉 {}
。如果表达式的结果为一个对象,则 Dart 会调用该对象的 toString
方法来获取一个字符串。
可以使用 +
运算符或并列放置多个字符串来连接字符串。使用三个单引号或者三个双引号也能创建多行字符串。
在字符串前加上 r
作为前缀创建 “raw” 字符串(即不会被做任何处理(比如转义)的字符串)。
你可以查阅 Runes 与 grapheme clusters 获取更多关于如何在字符串中表示 Unicode 字符的信息。
字符串字面量是一个编译时常量,只要是编译时常量 (null、数字、字符串、布尔) 都可以作为字符串字面量的插值表达式:
// These work in a const string.
const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';
// These do NOT work in a const string.
var aNum = 0;
var aBool = true;
var aString = 'a string';
const aConstList = [1, 2, 3];
const validConstString = '$aConstNum $aConstBool $aConstString';
// const invalidConstString = '$aNum $aBool $aString $aConstList';
可以查阅 字符串和正则表达式 获取更多关于如何使用字符串的信息。
布尔类型
Dart 使用 bool
关键字表示布尔类型,布尔类型只有两个对象 true
和 false
,两者都是编译时常量。
Dart 的类型安全不允许你使用类似 if (nonbooleanValue)
或者 assert (nonbooleanValue)
这样的代码检查布尔值。相反,你应该总是显示地检查布尔值。
List
数组 (Array) 是几乎所有编程语言中最常见的集合类型,在 Dart 中数组由 List 对象表示。通常称之为 List。
List 的下标索引从 0 开始,第一个元素的下标为 0,最后一个元素的下标为 list.length - 1
。
在 List 字面量前添加 const
关键字会创建一个编译时常量。
var constantList = const [1, 2, 3];
// constantList[1] = 1; // This line will cause an error.
Dart 在 2.3 引入了 扩展操作符(...
)和 空感知扩展操作符(...?
),它们提供了一种将多个元素插入集合的简洁方法。
例如,你可以使用扩展操作符(...
)将一个 List 中的所有元素插入到另一个 List 中:
var list = [1, 2, 3];
var list2 = [0, ...list];
assert(list2.length == 4);
如果扩展操作符右边可能为 null
,你可以使用 null-aware 扩展操作符(...?
)来避免产生异常:
var list2 = [0, ...?list];
assert(list2.length == 1);
可以查阅扩展操作符建议获取更多关于如何使用扩展操作符的信息。
Dart 还同时引入了 集合中的 if 和 集合中的 for 操作,在构建集合时,可以使用条件判断 (if
) 和循环 (for
)。
下面示例是使用 集合中的 if 来创建一个 List 的示例,它可能包含 3 个或 4 个元素:
var nav = ['Home', 'Furniture', 'Plants', if (promoActive) 'Outlet'];
下面是使用 集合中的 for 将列表中的元素修改后添加到另一个列表中的示例:
var listOfInts = [1, 2, 3];
var listOfStrings = ['#0', for (var i in listOfInts) '#$i'];
assert(listOfStrings[1] == '#1');
你可以查阅 集合中使用控制流建议 获取更多关于在集合中使用 if
和 for
的细节内容和示例。
List 类中有许多用于操作 List 的便捷方法,你可以查阅 泛型 和 集合 获取更多与之相关的信息。
Set
在 Dart 中,set
是一组特定元素的无序集合。 Dart 支持的集合由集合的字面量(literals)和 Set 类提供。
set 还是 map? Map 字面量语法相似于 Set 字面量语法。因为先有的 Map 字面量语法,所以
{}
默认是 Map 类型。如果忘记在{}
上注释类型或赋值到一个未声明类型的变量上,那么 Dart 会创建一个类型为Map<dynamic, dynamic>
的对象。
使用 add()
方法或 addAll()
方法向已存在的 Set 中添加项目。使用 .length
可以获取 Set 中元素的数量。可以在 Set 变量前添加 const
关键字创建一个 Set 编译时常量。
从 Dart 2.3 开始,Set 可以像 List 一样支持使用扩展操作符(...
和 ...?
)以及 Collection if
和 for
操作。你可以查阅 List 扩展操作符 和 List 集合操作符 获取更多相关信息。
Map
通常来说,Map 是用来关联 keys 和 values 的对象。其中键和值都可以是任何类型的对象。每个 键 只能出现一次但是 值 可以重复出现多次。 Dart 中 Map 提供了 Map 字面量以及 Map 类型两种形式的 Map。
如果你之前是使用的 C# 或 Java 这样的语言,也许你想使用
new Map()
构造 Map 对象。但是在 Dart 中,new
关键词是可选的。(且不被建议使用) 你可以查阅 构造函数的使用 获取更多相关信息。
如果检索的 Key 不存在于 Map 中则会返回一个 null。使用 .length
可以获取 Map 中键值对的数量。在一个 Map 字面量前添加 const
关键字可以创建一个 Map 编译时常量。
Map 可以像 List 一样支持使用扩展操作符(...
和 ...?
)以及集合的 if 和 for 操作。
Runes 与 grapheme cluster
在 Dart 中,runes 公开了字符串的 Unicode 码位。使用 characters 包 来访问或者操作用户感知的字符,也被称为 Unicode (扩展) grapheme clusters。
Unicode 编码为每一个字母、数字和符号都定义了一个唯一的数值。因为 Dart 中的字符串是一个 UTF-16 的字符序列,所以如果想要表示 32 位的 Unicode 数值则需要一种特殊的语法。
表示 Unicode 字符的常见方式是使用 \uXXXX
,其中 XXXX 是一个四位数的 16 进制数字。例如心形字符(♥)的 Unicode 为 \u2665
。对于不是四位数的 16 进制数字,需要使用大括号将其括起来。例如大笑的 emoji 表情(
标签:Map,const,变量,之旅,Dart,使用,类型,语言 来源: https://www.cnblogs.com/geekfx/p/16319300.html