--- title: dart初见(1) date: 2019-09-28 12:08:40 tags: - dart categories: - flutter --- Flutter是谷歌推出的跨平台移动端开发框架 它使用dart这门小众语言作为开发语言 想到自己在移动端开发这块的技能还相对薄弱,所以最近学习了一下这门语言,为学习Flutter框架稍作准备 dart的代码语句末尾必须写分号 学习一门编程语言,当然要先了解这门语言的基础设施 ### 变量与数据类型 dart语言有类型推导机制,但仍然是强类型语言 未初始化的变量值均为null,如果一个变量未在定义时被初始化,那么它的类型就不会被确定 可以指向任意类型的对象 ```dart void main() { var num1 = 10; num1 = 'hello'; // 错误 print(num1); var num2; num2 = 10; num2 = 'hello'; // 正确 print(num1); } ``` 用`var`来定义变量会执行类型推导 也可以用`int`等类型名称直接声明变量类型,比如`int a = 10;` #### 内置的数据类型 + **数值型-Number** - 用`num`表示,包含`int`和`double`两种子类型,分别表示整数和浮点数 + **字符串-String** - 用`String`表示 + **布尔型-Boolean** - 用`bool`表示,分为true和false + **列表-List** - 用`List`表示,用诸如 **\[10,'ab',15.9\]** 的形式声明一个列表(类似python) 前面加const表示不可变的List + **无序集合-Set** - 用`Set`表示,用诸如 **{10,'ab',15.9}** 的形式声明一个无序集合,集合中的元素是唯一的 + **键值对-Map** - 用`Map`表示,用诸如 **{'a':10, 'b':20}** 的形式声明一个键值对的集合 + Runes、Symbols 这些本质上都是dart内置的类,比如int和double这两个类就是继承自num类的 #### final与const 用final修饰的变量,必须在定义时将其初始化,其值在初始化后不可改变;const用来定义常量 它们的区别在于,const比final更加严格。final只是要求变量在初始化后值不变,但通过final,我们无法在编译时(运行之前)知道这个变量的值 而const所修饰的是编译时常量,我们在编译时就已经知道了它的值,显然,它的值也是不可改变的。 ```dart void main() { final int m1 = 60; final int m2 = func(); // 正确 const int n1 = 42; const int n2 = func(); // 错误 } int func() { return 500; } ``` 上面的例子当中,显然编译期是无法知道func函数的执行结果的,所以无法用const变量接收其返回值 ### 数值型操作 针对数值的运算符,大部分都和其他语言差不多 有差别的是多一个`~/`运算符,它表示取整的除法,直接使用`/`是保留小数部分的 `%`取余运算是不取整的 常用属性 + `isNaN` - 0/0的运算会得到一个NaN,可以用来做判断 + `isEven` - 是否是偶数 + `isOdd` - 是否是奇数 常用方法 + `abs()` - 取绝对值 + `round()` - 四舍五入 + `floor()` - 向下取整 + `ceil()` - 向上取整 + `toInt()` - 转换为int类型 + `toDouble()` - 转换为double类型 ### 字符串操作 1. 使用单引号或双引号来表示字符串常量 2. 三个单引号或双引号可以表示多行字符串 3. 使用`r`创建原始raw字符串 前两种都很简单,和js也类似 第三种的意思是是否对转义字符进行处理 ```dart String str1 = 'a\nb'; String str2 = r'a\nb'; print(str1); // a b print(str2); // a\tb ``` 第一个转义字符是起作用的,第二个则不会对转义字符进行处理 运算符 + `+` - 字符串拼接(注意字符串不能与非字符串类型的常量或变量进行拼接) + `*` - 后面跟的是次数,表示把该字符串重复若干次 + `==` - 判断是否相同 + `[]` - 获取字符串指定索引位置的字符(从0开始) 插值表达式`${expression}` ```dart int a = 10; int b = 20; print('a=$a'); // 如果只是一个变量 也可以不写大括号 print('a+b=${a+b}'); ``` 常用属性 + `length` - 字符串长度 + `isEmpty` - 是否是空串 + `isNotEmpty` - 是否不是空串 常用方法 + `contains(str)`,`subString(start,end)` - 是否包含某个子串,取子串(end不传则截取到末尾) + `startWith(str)`,`endsWith(str)` - 是否以某个字符串开头/结尾 + `indexOf(str)`,`lastIndexOf(str)` - 子串第一次/最后一次出现的位置 + `toUpperCase()`,`toLowerCase()` - 转换为大写/小写 + `trim()`,`trimLeft()`,`trimRight()` - 去除首/尾的空白字符 + `split(str)` - 分割字符串,得到一个List对象 + `replaceAll(form,str)` - 正则替换 replace有一系列的方法 第一个参数可以是字符串也可以是正则对象 ```dart String str1 = 'ab123cd45'; RegExp numReg = new RegExp(r'\d+'); // 也可以写 '\\d+' print(str1.replaceAll(numReg, '..')); // ab..cd.. ``` ### List操作 一个List在定义之后,可以使用类似数组操作的方式用`[]`获取指定下标的元素以及修改指定元素 使用`length`属性获取List的长度 但是不能像js那样对越界的下标直接赋值 常用方法 + `add(value)`,`insert(index,value)` - 添加元素/在指定位置添加元素 + `remove(value)`,`removeAt(index)` - 移除指定元素/指定位置的元素 + `indexOf(value)`,`lastIndexOf(value)` - 查找元素第一次/最后一次出现的位置,找不到返回-1 + `sort(func)` - 以指定规则排序 > dart同样支持函数式编程 sort就需要传入一个函数对象,这个函数需要返回一个整数 正数表示大于,负数表示小于,0表示等于 ```dart List list1 = ['aa','b','cccc','ddd']; list1.sort((a,b) => a.length.compareTo(b.length));//[b, aa, ddd, cccc] ``` + `shuffle()` - 随机乱序 + `asMap()` - 转换为下标为key,元素为value的键值对集合 + `forEach(func)` - 对List执行遍历(传入一个函数) ### Map操作 使用`[]`的方式获取或修改Map当中的元素 `length`可以获取Map的键值对数量 `keys`和`values`可以获取键和值的集合 常用方法 + `isEmpty()`,`isNotEmpty()` - 判断是否(不)为空 + `containsKey(key)`,`containsValue(value)` - 是否包含某个键/值 + `remove(key)` - 按照key移除某个键值对 + `forEach(func)` - 遍历Map ### dynamic与泛型 dart语言当中使用`dynamic`来表示动态类型 ```dart var a; a = 10; a = 'abc'; // a就相当于是dynamic类型的一个变量 // 也可以这样定义变量 dynamic b = 20; b = 'cde'; ``` 对于集合类型,可以指定泛型,或者使用dynamic来表示任意类型 比如 ```dart Map map = new Map(); ``` 就表示这个Map的key必须是字符串,value可以是任意类型 ### 条件表达式与运算符 dart当中除了常规的赋值与三目运算符之外 还有`??`运算符以及`??=`赋值运算符 ```dart int a = 10; a ??= 20; print(a); // 10 int b; int c = b ?? 30; print(c); // 30 ``` + `??=` 代表为左值空的时候就执行赋值,否则就什么都不做 + `expr1 ?? expr2` 代表判断expr1是否为null,如果为null就取expr2的值,否则就取expr1的值 ### switch语句的差异 dart当中的switch与其他语言的用法基本一致 有一点差别就是 > 不是switch当中的最后一个case 其最后一个语句必须是下列关键字其中之一 `break`, `continue`, `rethrow`, `return` or `throw` + `continue`后面必须跟一个label的名称,label必须是在这个switch当中某个位置指定的标签 ```dart void func(String name) { switch(name) { case 'Sookie' : print(1); continue label1; case 'Alice' : print(2); break; label1: case 'Lily' : print(3); } } ``` + `rethrow`可以写在catch块当中,代表在捕获异常的同时进行传播