Dart 开发语言概览

发布时间 2023-06-24 23:38:02作者: 白乾涛

本文地址


目录

Dart 开发语言概览

重要概念

以下均假设开启了 空安全

  • 所有变量引用的都是 对象,每个对象都是一个 类 的实例
    • 数字、函数以及 null 都是对象
    • 除去 null 以外, 所有的类都继承于 Object
  • Dart 是强类型语言,但是在声明变量时可不显示指定类型,因为 Dart 可以进行类型推断
  • 变量在未声明为可空类型时不能为 null
    • 可以通过在类型后加上问号 ? 将类型声明为可空
    • 可以在表达式后添加 ! 来断言表达式不为空(为空时将抛出异常)
  • Dart 中可使用 Object? 或者 dynamic 表示任意类型
    • 在编译时,任何成员对 dynamic 类型值访问都是允许的,但在运行时可能会引发异常
    • 避免使用 dynamic,除非你希望禁用静态检查 (Indicates that you want to disable static checking)
  • Dart 支持泛型,比如 List<int>
  • Dart 支持顶级函数,支持定义属于类或对象的函数(即 静态 和 实例方法),支持 函数嵌套 或 局部函数
  • Dart 支持顶级变量,支持定义属于类或对象的变量(即 静态 和 实例变量),实例变量有时称之为域或属性
  • Dart 没有类似于 Java 那样的 public、protected 和 private 成员访问限定符
    • 标识符可以以字母或者下划线 _ 开头
    • 以下划线 _ 开头时表示该标识符在内是私有的
  • Dart 中表达式有值而语句没有值
  • Dart 工具可以显示 警告 和 错误 两种类型的问题
    • 警告表明代码可能有问题但不会阻止其运行
    • 错误分为编译时错误和运行时错误;编译时错误代码无法运行;运行时错误会在代码运行时导致异常

变量

  • 变量仅存储对象的引用,而非对象的值
  • 在 Dart 中一切皆为对象,数字也不例外
  • 建议通过 var 声明局部变量,而非使用指定的类型
    • 因为函数往往很短,省略局部变量类型会将读者的注意力集中在变量的 名称 及初始化值上
  • 并不需要在声明变量时初始化,只需在第一次用到这个变量前初始化即可

late

  • 可以在声明变量时用 late 修饰,用来延迟初始化一个变量
  • late 修饰的变量在使用前没有初始化,会抛出运行时异常 -- 即使变量是可空类型
  • late 修饰的变量在声明时指定了初始化方法,那么初始化过程会且仅会发生在第一次被使用的时候
String? s1;
late String? s2;

void main() {
  assert(s1 == null);
  print(s1); // null
  print(s2); // LateInitializationError: Field 's2' has not been initialized.
}
  • 在生产环境,assert() 的调用将会被忽略掉
  • 在开发过程,assert(condition) 将会在 condition 为 false 时抛出一个异常

final 和 const

  • 关键字 finalconst 可以替代 var 关键字,也可以加在一个具体的类型前
  • final 变量只可以被赋值一次
  • const 变量是一个编译时常量, const 变量同时也是 final
  • 如果使用 const 修饰类中的变量,则必须加上 static 关键字,即 static const, 顺序不能颠倒
final s1 = null;
final String s2 = "s2";
late final s3;

const name = "bqt";
const double pi = 3.14;
  • const 也可以用来创建 常量值,该常量值可以赋予给任何变量
  • const 也可以用来修饰 构造函数,这种类型的构造函数创建的对象是不可改变的
var c1 = const [1, 2];   // 普通变量,可以被修改
final c2 = const [1, 2]; // final 变量,不可修改
const c3 = [1, 2];       // const 变量,不可修改
const c4 = const [1, 2]; // const 变量,不可修改

void main() {
  c1 = [666]; // [666]
  print(c1);
}

注释

  • 单行注释: //
  • 多行注释: 以 /* 开始,以 */ 结尾
  • 文档注释: 以 /// 或者 /** 开始
    • 文档注释可以是多行注释,也可以是单行注释
    • 可以使用中括号引用类、方法、字段、顶级变量、函数和参数
    • 在生成的文档中,[xxx] 会成为一个链接,指向 xxx 方法/类/字段的文档

内置类型

内置类型

数字 int double

  • 整数 int 是不带小数点的数字
  • 如果包含小数点,那么它就是浮点型 double
  • 整型字面量可自动转换成浮点数字面量
  • 数字字面量为编译时常量
  • 很多算术表达式,只要其操作数是常量,则表达式结果也是编译时常量

var x = 1;
var hex = 0xDEADBEEF; // 16^8 = 2^(4*8) 即 32 位

var y = 1.1;
var exponents = 1.42e5;
double z = 1; // Equivalent to double z = 1.0.

var one = int.parse('1'); // String -> int
var onePointOne = double.parse('1.1'); // String -> double

字符串 String

  • 可以使用单引号或者双引号来创建字符串
  • 使用单引号创建字符串时,可以使用斜杠来转义那些与单引号冲突的字符串
  • 如果 ${表达式} 的结果为一个对象,则 Dart 会调用该对象的 toString 方法来获取一个字符串
  • 可以使用 + 运算符或 并列放置 多个字符串(即便它们不在同一行)来连接字符串
  • 使用三个单引号或者三个双引号也能创建多行字符串
  • 在字符串前加上 r 作为前缀创建 raw 字符串, 即不会被做任何处理(比如转义)的字符串
var s1 = '可以拼接'
    '字符串'
    "即便它们不在同一行。";
assert(s1 == '可以拼接字符串即便它们不在同一行。');

var s2 = '''
You can create
multi-line strings like this one.
''';
print(s2);

var s3 = r'在 raw 字符串中,转义字符串 \n 会直接输出 "\n" 而不是转义为换行。';
print(s3);

const cList = [1, 2];
const cString = '$cList'; // 仅 null、num、String、bool 可以作为字符串字面量的插值表达式

布尔 bool

  • Dart 使用 bool 关键字表示布尔类型
  • 布尔类型只有两个对象 truefalse,两者都是编译时常量

数组 List

  • 可以在 Dart 的集合类型的最后一个项目后添加逗号
  • 在 List 字面量前添加 const 关键字会创建一个编译时常量
  • 扩展操作符 ...: 将一个 List 中的所有元素插入到另一个 List 中
  • 如果扩展操作符右边可能为 null ,可以使用 ...? 来避免产生异常
var list = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);

var constantList = const [1, 2, 3];

var list2 = [0, ...list]; // 扩展操作符
assert(list2.length == 4);
var list3 = [0, ...?list]; // 空感知扩展操作符

在构建集合时,可以使用条件判断 if 和循环 for

var nav = ['Home', 'Furniture', 'Plants', if (promoActive) 'Outlet'];

var listOfInts = [1, 2, 3];
var listOfStrings = ['#0', for (var i in listOfInts) '#$i'];
assert(listOfStrings[1] == '#1');

无序集合 Set

  • Set 是一组特定元素的无序集合
  • 可以使用在 {} 前加上类型参数的方式创建一个空的 Set,或者将 {} 赋值给一个 Set 类型的变量
  • 可以在 Set 变量前添加 const 关键字创建一个 Set 编译时常量
  • 可以像 List 一样支持使用扩展操作符以及 Collection if 和 for 操作
var set = const {'a', 'c', '1', 'b'};

var names1 = <String>{}; // 创建一个空的 Set
Set<String> names2 = {}; // 创建一个空的 Set
var names3 = {};         // 类型为 Map<dynamic, dynamic>

names1.add("bqt");          // 添加项目
names1.addAll(names2);      // 添加所有项目
print(names1.elementAt(0)); // 获取项目
print(names1.length);       // 获取元素数量

键值对 Map

  • Map 是用来关联 keys 和 values 的对象,其中键和值都可以是任何类型的对象
  • 每个 键 只能出现一次,但是 值 可以重复出现多次
  • 在一个 Map 字面量前添加 const 关键字可以创建一个 Map 编译时常量
  • 可以像 List 一样支持使用扩展操作符以及 Collection if 和 for 操作
var map1 = Map<String, String>();
map1['first'] = 'bqt';

var map2 = { 2: 'bqt'}; // 类型推断为 Map<int, String>

函数

2023-06-24