Flutter Dart语言(01)环境安装&基础语法总结

本教程针对有C/C++基础的程序员,介绍Dart语言,包括Dart的起源、环境安装、VSCode配置、变量类型(如int、double、num、var)、字符串操作、列表(List)、集合(Set)、映射(Map)的使用,以及Dart的null安全机制。文章通过代码示例详细讲解了Dart的基础知识和新特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 变量关键知识点总结

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不行,必须最开始就初始化。

3.6.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.6.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
}

3.6.4 as类型强制转换关键字

与C/C++相比,强制转换更简单了,简单的实现,代码实现如下所示:

(p1 as Person).printInfo();

4 新特性总结

4.1 null safety机制

使用空(null)值可能会导致程序崩溃或产生不可预期行为。空安全机制本质是帮助developer 检测并避免使用空值。这意味着每个变量都必须具有非null值或明确声明其可为空性。这里做一个简单测试,相关代码实现如下:

void main() {
  //?符号-设置其可空性
  String? str = "test";
  //如果上一句是String str = "test"; 则无法赋值为空
  str = null;

  //如果下面直接输出 str.length则因为 str==null而报错,编译都不过
  print(str!.length);//注意:str==null时,会抛出异常
}

4.2 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图王大胜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值