本文章是博主在此网站学习 Dart 语言时所摘录的一些重要内容,用于快速掌握 Dart 语言,详细完整内容请点击原网页。
重要概念
- Dart 万物皆对象,并且所有的对象都是对应一个 类 的实例。
- 尽管 Dart 是强类型的,但是 Dart 可以推断类型,所以类型注释是可选的。
- Dart 支持顶级函数(例如
main()
), 同样函数绑定在类或对象上(分别是 静态函数 和 实例函数 )。 以及支持函数内创建函数 ( 嵌套 或 局部函数 ) 。 - 类似地, Dart 支持顶级变量 , 同样变量绑定在类或对象上(静态变量和实例变量)。 实例变量有时称为字段或属性。
- Dart 没有关键字 “public” , “protected” 和 “private” 。 如果标识符以下划线(_)开头,则它相对于库是私有的。
操作符
~/
:返回除法运算的整数值;is
:当对象是相应类型时返回 true;is!
:当对象不是相应类型时返回 true;a ?? b
:如果 a 为非空,则返回其值;否则,计算并返回 b 的值;a ??= b
:在变量 a 为 null 时赋值;...
:可把 list、set、map 字面量里的元素插入到一个集合中,对象可为空,则使用...?
;
变量和常量
如果对象不限定为单个类型,可以指定为 对象类型
或 动态类型
:
1 | dynamic name = 'Mahoo12138'; |
未初始化的变量默认值是 null
。即使变量是数字类型默认值也是 null,因为在 Dart 中一切都是对象,数字类型也不例外:
1 | int lineCount; |
在生产环境代码中
assert()
函数会被忽略,不会被调用。 在开发过程中,assert(condition)
会在非true
的条件下抛出异常
Final 变量的值只能被设置一次; Const 变量在编译时就已经固定 (Const 变量是隐式 Final 的类型),常量如果是类级别的,请使用 static const
类与函数
Dart 使用
class
关键字表示一个类,对象具有由函数和数据(分别为方法和实例变量)组成的成员,未初始化实例变量的默认值为 “null”。抽象类不能被实例化,可以通过实例化继承自该抽象类的子类使用,当然也能使用
implement
直接当作接口(implement 并不局限于抽象类,普通类同样可以),使用接口时,需要将接口内的方法和属性需要全部定义或重写,接口的作用个人理解成是一种具体代码之间的规范化。类中的
final
关键字修饰的变量不能被修改,而且必须被构造函数初始化。类中的
static
关键字修饰的变量为静态变量,其固属于这个类,并不属于类的实例,不能用this
访问到;static
关键字修饰的函数即为静态函数,类似于静态变量:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Person {
static String name = 'mahoo12138';
static show() {
print(name);
}
}
main(){
print(Person.name);
Person.show();
var p = Person();
// print(p.name); !报错
// p.show(); !报错
}
>> 输出
mahoo12138
mahoo12138构造函数的名称可以是类名
ClassName
或者类名和标识符ClassName.identifier
。 其中构造函数名称是“ClassName”的函数叫类名构造函数;构造函数名称是“ClassName.identifier”的函数叫命名构造函数。默认构造函数——在没有声明构造函数的情况下, Dart 会提供一个默认的构造函数。 默认构造函数没有参数并会调用父类的无参构造函数。
构造函数不被继承
子类不会继承父类的构造函数。 子类不声明构造函数,那么它就只有默认构造函数 (匿名,没有参数) :
1 | class Point { |
调用父类非默认构造函数
默认情况下,子类的构造函数会自动调用父类的默认构造函数(未命名,无参数),如果父类中没有匿名无参的构造函数, 则需要手工调用父类的其他构造函数。 在当前构造函数冒号 (:
) 之后,函数体之前,声明调用父类构造函数:
1 | class Person { |
构造函数的调用顺序
子类的构造函数中执行的操作顺序如下:
初始化列表
父类的无参构造函数
本类的无参构造函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42void main() {
var result = new TestChild.area(3, 4);
print('面积为:${result.area}');
// Print:
// Test 空参构造
// TestChild 有参构造
// 面积为:6.0
}
class Test {
num width;
num height;
num area;
// 必须加上空参构造,如果注释掉 它的子类会报错
Test() {
print('Test 空参构造');
}
Test.area(width, height)
: width = width,
height = height,
area = width * height {
print('Test 有参构造');
}
}
class TestChild extends Test {
num width;
num height;
num area;
TestChild() {
print('TestChild 空参构造');
}
TestChild.area(num width, num height)
: area = (width * height)/2 {
print('TestChild 有参构造');
}
}
重定向构造函数
有时构造函数的唯一目的是重定向到同一个类中的另一个构造函数。重定向构造函数的主体是空的,构造函数调用出现在冒号
:
之后:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20void main() {
var result = new Test(4, true, '数字', 10);
var result1 = new Test.test1(4, true);
var result2 = new Test.test2(1,false,'mahoo')
}
class Test {
num a;
bool b;
String c;
num d;
// 主构造函数
Test(this.a, this.b, this.c, this.d);
// 委托给主构造函数
Test.test1(num x,bool y) : this(x, y,'', 0);
Test.test2(num a,bool b, String c) : this(a, b, c, 0);
Test.test3(num a,bool b, String c,num d) : this(a, b, c, d);
}要在运行时获取对象的类型,可以使用Object类的
runtimeType
属性,该属性返回一个Type对象1
2var a = 10;
print('a 的类型是: ${a.runtimeType}'); // a 的类型是: intDart和Java一样,使用
extends
关键字,表示一个类继承另一个类。使用
static
关键字修饰的类范围的变量。静态变量(类变量)对于类范围的状态和常量很有用。静态变量在使用之前不会初始化。使用
abstract
修饰符定义抽象类(无法实例化的类)。抽象类对于定义接口非常有用,通常还有一些实现。如果希望抽象类看起来是可实例化的,请定义工厂构造函数。
工厂构造函数
当执行构造函数并不总是创建这个类的一个新实例时,则使用 factory 关键字。 例如,一个工厂构造函数可能会返回一个 cache 中的实例, 或者可能返回一个子类的实例。
工厂构造函数是通过代码来决定返回的实例对象;工厂构造函数类似于 static 静态成员,无法访问 this 指针;一般需要依赖其他类型构造函数:
1 | class People { |
工厂构造函数还可以实现单例:
1 | class Singleton { |
Typedef
目前,typedef 只能使用在函数类型上,对函数类型的对象做一个别名,例如:
1 | typedef Compare = int Function(Object a, Object b); |
int Function(Object a, Object b);
为一个函数类型的对象的类型信息。
Runes
Runes 对象是一个 32位 字符对象,用来表示一个字。这样设计也是考虑兼容 UTF-16 四个字节的情况。
我们来看一个示例,打开网页CopyChar – Copy special characters to your clipboard,选择一个 Emoji 小丑,编辑代码:
1 | String a = '🤡'; |
由此可知,runes 是一个 32 位字符对象,联系到实际的开发,例如在一款实时聊天的软件中,用户输入 emoji 表情时,如果使用字符串的 length 方法就会造成统计字符数量出现错误,这时 runes 的作用就体现出来了。
常用的 API:
1 | /// 操作 32-bit Unicode 字符 |