淘先锋技术网

首页 1 2 3 4 5 6 7

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
}