- Dart 语言的入口是
main
函数,并且必须显式定义。Dart 语言的main
函数没有返回值。传递给main
函数的命令行参数,是通过List<String>
完成的。List
是集合类型,每一个String
都表示一个参数。 - Dart 语言中打印信息使用
print
函数。 - Dart 语言中定义字符串可以使用单引号或双引号。
- Dart 语言中每行代码必须使用分号结尾。
- 编写 Dart 语言创建的文件是
.dart
文件。
Dart源码:安装过 Flutter 后,可以在 /Applications/flutter/bin/cache/dart-sdk/lib/core/
找到 Dart 的源码。
环境搭建
基本语法
main
函数是 Dart 入口;- Dart 中打印使用
print
;
main
函数的返回值是空 void
,在 Dart 中返回值可以省略,由系统自动进行类型判断。
|
|
声明变量
1、明确的声明
- 变量类型 变量名 = 赋值;
|
|
2、类型推导
var
用于定义变量,final
、const
用于定义常量。使用他们定义变量或常量时,虽然没有明确指定变量的类型,但是在编译时变量可以明确自己的类型。
使用 var
定义变量:
|
|
使用 final
定义常量:
|
|
使用 const
定义常量:
|
|
final
和 const
的区别:
const
在赋值时,赋值的内容必须在编译期间就确定下来。final
在赋值时,可以动态获取,如通过计算、函数返回等方式获取一个值,在运行期间来确定一个值。
可以通过函数给 final 赋值:
|
|
final
可以定义两个相同类型的常量。
|
|
const
可以让一个类型只创建一个常量。
|
|
在日常开发中定义常量多使用 final
。
可以使用 runtimeType
获取变量当前的类型:
|
|
布尔类型
Dart 中不能判断非零即真,或者非空即真。Bool 类型必须是一个确定的实体。
|
|
字符串类型
Dart 字符串是 UTF-16 编码单元的序列,可以使用单引号或双引号创建一个字符串:
|
|
可以使用三个单引号或者双引号表示多行字符串
|
|
打印结果:
|
|
- 字符串的拼接
字符串和其他变量或表达式拼接时,使用${expression}
表达式,如果 expression 是一个标识符,那么 {}
可以省略:
|
|
如果不是一个标识符,则不可以省略 {}
:
|
|
数字转字符串:
|
|
字符串转数字:
|
|
集合
1、列表List:[]
|
|
2、集合Set:{}
|
|
3、映射Map
|
|
增删改查
1、列表 List
|
|
2、集合 Set
|
|
3、映射 Map
|
|
函数
基本使用
|
|
sum
函数的参数和返回值都是 int
类型,其中返回值类型可以省略,由 Dart 自动推断:
|
|
- 如果函数中只有一个表达式,可以使用箭头语法(arrow syntax)
=>
|
|
可选参数
在 Dart 中没有函数重载。参数类型分为三类:
- 必选参数;
- 位置可选参数;
- 命名可选参数;
必选参数
|
|
可选参数有两种:
- 位置可选参数:[param1, param2, …];
- 命名可选参数:{param1, param2, …};
命名可选参数
- 命名可选参数:{param1, param2, …};
位置不确定,但是形参必须要写。
|
|
位置可选参数
- 位置可选参数:[param1, param2, …];
不需要写名形参,实参和形参在进行匹配时,是根据位置的匹配。
|
|
参数默认值
在不传参数的情况下,使用默认值。
|
|
函数是一等公民
函数作为一等公民,即可以赋值给一个变量,也可以作为另一个函数的参数或这返回值。
1、将函数赋值给一个变量:
|
|
可以看到 hello
是一个 Closure: (String) => dynamic
的类型的函数。
2、将函数作为另一个函数的参数:
|
|
3、将函数作为另一个函数的返回值:
|
|
4、自定义函数类型
|
|
匿名函数
匿名闭包(anonymous function),也叫作 lambda 或 闭包(closure)。定义一个没有名字的函数,作为函数的参数或返回值,提高编码效率。
|
|
say
函数的返回值为 void
,参数是一个函数,该函数的参数是 String
类型,函数体是一个打印方法:
|
|
示例二:使用 forEach
遍历
|
|
打印结果:
|
|
词法作用域
优先使用自己作用域中的变量,如果没有找到,则一层层向外查找。
|
|
|
|
|
|
词法闭包
|
|
创建出来的 adder
记住了创建时传入的 2。
隐式返回
所有函数都有一个返回值。如果没有指定返回值,则默认返回 null
。
|
|
特殊运算符
??
空值合并运算符
|
|
??=
空值赋值运算符
|
|
..
级联运算符
|
|
打印信息:
|
|
for
循环
|
|
for-in
循环
|
|
Dart之面向对象
类的定义
|
|
1、初始化类时,类名前的 new
可以省略:
|
|
2、Dart 语言要求类的成员变量,在类初始化前要有确定的值。如果没有在初始化时给成员变量赋值,就会报错:
类的构造函数
|
|
使用 json 初始化类:
|
|
初始化列表
- 初始化列表会在构造函数前执行,常用于设置
final
变量的值,使用逗号,
分隔初始化表达式。
|
|
在创建对象时,可以选择传或不传 age
,不传使用默认值:
|
|
Dart 3.0 后,使用 ?
表示 age
可能为 null
,在可选参数列表中使用 ??
判断 age
是否有值。
widget
中 container
的相关源码(路径/Applications/flutter/packages/flutter/lib/src/widgets/container.dart
):
|
|
重定向构造方法
因为 Dart 不支持方法重载,所以对于有多个成员变量的类,不能写多个不同的构造方法:
可以使用构造函数重定向来实现这种场景:
|
|
工厂构造方法
普通的构造函数会自动返回创建出来的对象,不能手动返回:
|
|
工厂构造函数最大的特点是可以手动返回一个对象:
|
|
📢注意:这里的 _nameCache[name]!
加了 !
,表明一定不为 null
。这是 Dart 3.0 增加的能力-空安全类型系统。
setter 和 getter
|
|
类的继承
- 使用
extends
表示继承关系; - 子类的构造方法在执行前,将隐含调用父类的无参默认构造方法(没有参数且与类同名的构造方法)。
- 如果父类没有无参默认构造方法,则子类的构造方法必须在初始化列表中通过
super
显式调用父类的某个构造方法。
|
|
Object 和 dynamic 的区别
Dart 中所有类型都是 Object 的子类,包括 Function 和 Null。
- dynamic 与 Object 声明的变量都可以赋值任意对象,且后期可以改变赋值的类型。
Object 对象使用的属性和方法若不存在,编译时会报错。
dynamic 对象使用的属性和方法若不存在,编译时不会报错,运行时会报错。
抽象类的使用
📢注意一:继承自抽象类后,必须实现抽象类中没有实现的方法。
📢注意二:抽象类不能实例化。
必须实现抽象类中没有实现的方法:
|
|
可以重写抽象类中有实现的方法:
|
|
隐式接口
Dart 默认情况下所有的类都是隐式接口。在将一个类作为接口使用时,实现接口的类,必须实现这个接口中所有方法。通常将用于给别人实现的类声明为抽象类。
定义一个 Tom
类,继承自 Person
,使用 Run
、Swim
类作为接口:
|
|
通过 implements
实现某个类时,必须重新实现类定义的所有方法(无论这个类是否已经对方法实现)。如果想要直接复用之前类的原有实现方案,则可以使用 mixin
混入。
mixin混入的使用
想要直接复用之前类的原有实现方案,一般采取继承。但是因为 Dart 只支持单继承,所以无法直接复用多个类原有的实现方案。
想要直接复用多个类原有的实现方案,可以采用 Mixin 混入的方式:
- 使用
mixin
关键字定义一个类; - 使用
with
关键字来实现混入;
|
|
如果要类比的话,mixin
混入和 Swift 的协议有异曲同工之妙。
implements
和 with
关键字一起使用时,implements
要放最后:
|
|
类属性
|
|
类方法
|
|
枚举
选择器必须覆盖枚举类型的全部情况,否则会报错:
|
|
Dart中库的使用
一、使用系统库
使用 import '库的url'
的形式导入一个库。
|
|
库url有三种方式:
1、使用 dart:
表示 dart 标准库,
|
|
2、使用相对路径,导入项目中自定义的 .dart 文件:
|
|
3、Pub包管理系统中的库,使用前缀 package:
:
|
|
二、使用自定义库
1、as
关键字给库起别名。
当各个库有命名冲突的时候,可以使用 as
关键字来使用命名空间:
|
|
2、默认情况下,导入一个库时就是导入这个库中所有的内容。
show
:执行要导入的内容。
|
|
hide
:隐藏某个要导入的内容,导入其它内容。
|
|
3、将需要导入的库,使用 export
抽取到公共的 dart 文件
|
|
使用第三方库
|
|
参考 http 1.1.0