0 说明
该系列教程主要是为有一定语言基础 C/C++的程序员,快速学习一门新语言所采用的方法,属于在C/C++基础上扩展新语言的模式。
1 Dart语言简介
Dart亮相于2011年10月10日至12日在丹麦奥尔胡斯举行的GOTO大会,初衷是用于web、server、移动应用、物联网等领域的开发,语法跟C语言差不多、是面向对象、单继承的语言。
最开始是为解决JS的缺陷,但Node.js突然出现让JS可以在移动端跑起来,在这之后Dart就专注于跨平台了。后来搞出来一个移动开发框架Flutter,弯道超车进入移动端开发领域。在google的新系统Fuchsia 中大部分 UI 界面使用的是 Flutter,。dart的权重就直接上来了。
2 环境安装概要
针对于不同的操作系统,访问dart官网中页面-> 获取 Dart SDK | Dart,这里有现成的权威文档,linux、windows、mac都支持,按照步骤 执行即可。
为另外更好的体验,使用 vscode软件[ Visual Studio Code编辑器 ],无论哪个平台直接安装 dart 和 code runner插件即可。操作步骤各个平台都是一样的。code runner插件检索如下:
dart插件检索如下所示:
接下来就可以开始Dart语言的编写之旅了。来个 hello world 验证下,编写hello.dart文件
void main(){
print("hello world");
}
之后 点击右键,Run code,如下所示:
运行结果如下:
[Running] dart "/data/AGS/Dart/Project/hello.dart"
hello world
[Done] exited with code=0 in 0.305 seconds
接下来我们开始研究研究这玩意儿的语法(这里研究语法是以有C语言基础为前提的)。
3 基础语法-变量
3.1 变量基础知识
本质上和C语言很多地方类似,变量声明、定义、初始化,关键字等很多类似,但也有很多不同之处。这里更多是对和C语言不同的地方进行详细讲解。
@1 变量命名规则,Dart语言的标识符规则(和C/C++语言相差不大,标红处需注意):
- 标识符可以包括字符和数字。但是,标识符不能以数字开头。
- 除下划线(
_
)或美元符号($
)外,标识符不能包含特殊符号。 - 标识符不能是关键字。
- 它们必须是唯一的。
- 标识符区分大小写。
- 标识符不能包含空格。
3.2 数字型变量总结
C语言中 int float double 是基本数据类型,Dart中int double num(数字类型、可以是int / double中一种),而且还多了var弱类型,这玩意儿用起来省事儿不少。只不过类型名称上有些调整,这里用代码总结下:
void main() {
// 整型,整数值
var age1 = 2;
int age2 = 3;
// 浮点型
var salary1 = 44.44;
double salary2 = 55.55;
// num是int & double的父类,具体由dart自动推导
num age3 = 4;
num salary3 = 66.66;
print("$age1,$age2,$age3,$salary1,$salary2,$salary3");
}
运行后效果如下:
[Running] dart "/data/AGS/Dart/Project/hello.dart"
2,3,4,66.66,66.66,66.66
[Done] exited with code=0 in 0.265 seconds
3.3 字符串类型变量总结
总体上看比C语言在使用上是简化很多了,这里使用代码进行总结。
@1 常用字符串API总结
代码实现如下:
void main() {
// 定义普通字符串
var city1 = 'Beijing';
var city2 = "Shanghai";
// 定义多行字符串
var str1 = '''
1111111111111111.
aaaaaaaaaaaaaaaa.
''';
var str2 = """
222222222222222.
bbbbbbbbbbbbbbb.
""";
//使用${expression}将表达式的值放在字符串中
var str3 = '33333 $city1 ccccc.';
//使用相邻的字符串文字或+运算符来连接字符串
var str4 = city1 + city2;
//在前面加上r来创建“原始”字符串:
var str5 = r'In a raw string, not even \n gets special treatment.';
print(city1);
print(city2);
print(str1);
print(str2);
print(str3);
print(str4);
print(str5);
}
运行效果如下所示:
[Running] dart "/data/AGS/Dart/Project/hello.dart"
Beijing
Shanghai
1111111111111111.
aaaaaaaaaaaaaaaa.
222222222222222.
bbbbbbbbbbbbbbb.
33333 Beijing ccccc.
BeijingShanghai
In a raw string, not even \n gets special treatment.
[Done] exited with code=0 in 0.27 seconds
@2 字符串和数字相互转换API总结
代码实现如下:
void main() {
// String -> int
var i1 = int.parse('1');
print(i1);
// String -> double
var i2 = double.parse('1.1');
print(i2);
// int -> String
String str1 = 10.toString();
print(str1);
// double -> String
String str2 = 3.1415926.toString();
print(str2);
}
运行效果如下所示:
[Running] dart "/data/AGS/Dart/Project/hello.dart"
1
1.1
10
3.1415926
[Done] exited with code=0 in 0.297 seconds
3.4 List /Set /Map 使用总结
@1 List常用API总结
List常用代码总结,实现如下:
void main() {
List<String> list = ['1', '2'];
print(list[0]); // 1
/* 添加: add、addAll */
list.add('3');
print(list); // [1, 2, 3]
print(list.first); // 1
print(list.last); // 3
print(list.reversed.toList()); // [3, 2, 1]
list.addAll(['4', '5']);
print(list); // [1, 2, 3, 4, 5]
print("---------------------------");
/*insert、insertAll */
list.insert(1, '-');
print(list); // [1, -, 2, 3, 4, 5]
list.insertAll(0, ['6', '7']); // 根据index索引位置插入多条
print(list); // [6, 7, 1, -, 2, 3, 4, 5]
print("---------------------------");
/*remove*/
list.remove('6');
print(list); // [7, 1, -, 2, 3, 4, 5]
list.removeAt(0); // 根据index索引,删除那条数据
print(list); // [1, -, 2, 3, 4, 5]
list.removeLast();
print(list); // [1, -, 2, 3, 4]
list.removeRange(1, 2); // 根据index索引区间,从start索引开始删,到end索引不删除
print(list); // [1, 2, 3, 4]
print("---------------------------");
/*update*/
list[0] = '8';
print(list); // [8, 2, 3, 4]
//根据index索引区间, 从start索引开始更新,到end索引结束更新(end索引位置不更新的);
//索引区间无论多少条数据,以新的条数为准;
list.replaceRange(1, 3, ['9', '0']);
print(list); // [8, 9, 0, 4]
print("---------------------------");
/*iterator*/
list.forEach((item) {
print(item);
});
print("---------------------------");
/*级联操作符*/
list
..add('x')
..add('*');
print(list);
print("---------------------------");
}
运行结果如下所示:
[Running] dart "/data/AGS/Dart/Project/hello.dart"
1
[1, 2, 3]
1
3
[3, 2, 1]
[1, 2, 3, 4, 5]
---------------------------
[1, -, 2, 3, 4, 5]
[6, 7, 1, -, 2, 3, 4, 5]
---------------------------
[7, 1, -, 2, 3, 4, 5]
[1, -, 2, 3, 4, 5]
[1, -, 2, 3, 4]
[1, 2, 3, 4]
---------------------------
[8, 2, 3, 4]
[8, 9, 0, 4]
---------------------------
8
9
0
4
---------------------------
[8, 9, 0, 4, x, *]
---------------------------
[Done] exited with code=0 in 0.306 seconds
@2 Set常用API总结
Set常用代码总结,实现如下:
void main() {
Set set = {'a', 'b', 'c'};
/*add、addAll*/
set.add('d'); //{a,b,c,d}
print(set);
set.add('a'); //集合特性:重复元素 不会2次添加 {a,b,c,d}
print(set);
set.addAll(['e', 'f', 'g', 'h']); //{a,b,c,d,e,f,g,h}
print(set);
print(set.first); //a
print(set.last); // h
print(set.length); //8
print("--------------------------------------------------");
/*remove removeAll clear*/
set.remove('g'); //{a,b,c,d,e,f,h}
set.removeAll(['a', 'c', '2']); //对于Set不存在的元素会直接略过//{b,d,e,f,g,h}
print(set);
Set set2 = Set.from(set); //{b,d,e,f,g,h}
print(set2);
set2.clear(); //{}
print(set2);
print("--------------------------------------------------");
/*query contains*/
print(set.contains('a')); //false
print(set.contains('b')); //true
print(set.containsAll(['a', 'b'])); //false 表示同时包含a和b
print(set.elementAt(0)); //b
print("--------------------------------------------------");
/*iterate*/
/*i1*/
for (var item in set) {
print(item);
}
/*i2*/
set.toList().forEach((item) {
print(item);
});
print("--------------------------------------------------");
}
运行结果如下所示:
[Running] dart "/data/AGS/Dart/Project/hello.dart"
{a, b, c, d}
{a, b, c, d}
{a, b, c, d, e, f, g, h}
a
h
8
--------------------------------------------------
{b, d, e, f, h}
{b, d, e, f, h}
{}
--------------------------------------------------
false
true
false
b
--------------------------------------------------
b
d
e
f
h
b
d
e
f
h
--------------------------------------------------
[Done] exited with code=0 in 0.285 seconds
@3 Map常用API总结
Map常用代码总结,实现如下:
void main() {
Map map = {'name': 'zhangsan', 'age': 23};
print(map['name']); //zhangsan
/*add*/
map.addAll({'address': 'Beijing'});
map.addAll({'sex': 'Male'});
print(map); // {name: zhangsan, age: 23, address: Beijing ,sex: Male}
print(map.length); // 4
print(map.keys.toList()); //[name, age, address ,sex]
print(map.values.toList()); //[zhangsan, 23, Beijing, Male]
print("--------------------------------------------------");
/*iterate*/
map.forEach((key, value) {
print('key=$key value=$value');
/* key=name value=Zhangsan
key=age value=23
key=address value=Beijing
key=sex value=Male
*/
});
print("--------------------------------------------------");
/*update*/
map['name'] = 'Lisi';
print(map); //{name: Lisi, age: 23, address: Beijing ,sex: Male}
/*remove*/
print(map.isNotEmpty); // true
map.remove('name');
print(map); // {age: 23, address: Beijing}
map.clear();
print(map); // {}
print(map.isEmpty); // true
print("--------------------------------------------------");
}
运行结果如下所示:
[Running] dart "/data/AGS/Dart/Project/hello.dart"
zhangsan
{name: zhangsan, age: 23, address: Beijing, sex: Male}
4
[name, age, address, sex]
[zhangsan, 23, Beijing, Male]
--------------------------------------------------
key=name value=zhangsan
key=age value=23
key=address value=Beijing
key=sex value=Male
--------------------------------------------------
{name: Lisi, age: 23, address: Beijing, sex: Male}
true
{age: 23, address: Beijing, sex: Male}
{}
true
--------------------------------------------------
[Done] exited with code=0 in 0.277 seconds
3.5 Rune使用总结
Rune是用来表示字符串中的UTF-32编码字符。因为 Dart 字符串是基于一系列 UTF-16 编码单元, 因此要在字符串中表示32位Unicode值需要特殊的语法支持,如下所示:
void main() {
// Rune是UTF-32编码的特殊字符串。可以通过文字转换成符号表情或者代表特定的文字。
Runes emoji =
Runes('\u2665 \u{1f605} \u{1f60e} \u{1f47b} \u{1f596} \u{1f44d}');
print(String.fromCharCodes(emoji));
}
这玩意儿的用途感觉就是支持这种表情包 / 特殊字符。运行效果如下所示:
Running] dart "/data/AGS/Dart/Project/hello.dart"
♥ 😅 😎 👻 🖖 👍
[Done] exited with code=0 in 0.267 seconds
3.6 变量关键知识点总结
@1 final和const
两者都是声明不可更改变量,变量只能设置一次。但final不一定在声明时赋值,而const必须在定义的时候初始化。可以理解为const更加严格,这里使用代码清晰的描述下两者之间的区别,如下:
void main() {
//final vs const
final d11; //正确,运行时有确定的值
d11 = DateTime.now();
print(d11);
final d12 = DateTime.now(); //正确,运行时有确定的值
print(d12);
const d22 = DateTime.now(); //报错,抛出异常; 需要编译时有确定的值
}
可以看出final可以在声明时候不初始化,运行时根据需要只初始化一次,但const不行,必须最开始就初始化。
@2 Dart语言中的弱语言关键字var、Object、dynamic的区别
Dart是强类型语言,但也支持一些弱类型,Dart 中弱类型有var
, Object
以及dynamic,他们的区别如下所示:
- var 初始可定义, 如果有初始值,那么其类型将会被锁定,定义之后不可改变类型。
- Object 赋值后仍可改变变量类型。编译阶段检查类型。
- dynamic 赋值后仍可改变变量类型。编译阶段不检查类型。
这里使用代码清晰的描述下后两者之间的区别,如下:
void main() {
// dynamic vs Object
dynamic a = "xyz";
a = 2;
int b = a + 3;
print(b); // 5
Object c = "abc";
c = 2;
int d = c + 3;
print(d);
}
运行后效果如下:
[Running] dart "/data/AGS/Dart/Project/hello.dart"
hello.dart:10:13: Error: The operator '+' isn't defined for the class 'Object'.
- 'Object' is from 'dart:core'.
Try correcting the operator to an existing operator, or defining a '+' operator.
int d = c + 3; // 报错,抛出异常
^
[Done] exited with code=254 in 0.255 seconds
注意:所有类型都是Object的子类(包括Function和Null),所以任何类型的数据都可以赋值给Object声明的对象。Object 数据类型是确定的 , 因此不能调用 Object 类中不存在的方法。而dynamic可以根据自己需要使用任何数据类型的方法。
@3 类型判断 is关键字
与C/C++相比,多了这个类型判断的功能,目测很实用,也很简单,用法如下:
void main() {
var a = 198;
print(a is dynamic); // true
print(a is num); // true
print(a is int); // true
print(a is String); // false
}